import json
import os
import string
import time
import random
# from OthersMethod import OthersMethod
# from ProInfo import ProInfo
# from Common import Common
from loguru import logger
import jsonpath
import demjson
import requests
import datetime
import pytest

# from OfflineCalc import OfflineCalc

req_wares = []


class Common:
    def __init__(self):
        """
        多个接口通用的校验写在这里
        """
        pass

    def calc_result_check_proinfo_list(self, res_separate, exps=[]):
        """
        校验单个促销相关的各个字段值，包括促销语和享受次数等，入参为list，可以一次性校验多个促销

        线上线下算价通用

        :param res_separate:分解后的算价结果。格式：{'pros': pros_sort, 'shares': skus_share_info}
        :param exps:期望命中的促销列表，格式：exp = [{'proId_exp': 2021030500000881, 'proSlogan': 'XX', 'showSlogan': 'XX'}]
        """
        verification_res_all = {}
        log_all = [{'info': '\n'}, {'info': '================开始校验返回的单个促销相关的各个字段值================'}]
        proIds = []
        proIds_exp = []
        pros = res_separate['pros']
        for pro in pros:
            proIds.append(
                pro['proId'])  # 单品促销和bestoffer叠加的时候，如果命中单品促销的商品，在不同的bestoffer促销中做赠品/换购品。且没有剩余主品的情况下，会返回多个单品促销结构
        for exp in exps:
            verification_res = {}
            proId_exp = exp['proId_exp']
            proIds_exp.append(proId_exp)
            for pro in pros:
                if proId_exp == pro['proId']:
                    displayInfo = pro['displayInfo']
                    for key, value in exp.items():
                        if key[-3:] == 'exp':
                            continue
                        if pro.get(key) is not None:
                            if value == pro.get(key):
                                verification_res[key] = [True]
                            else:
                                exc_value = "促销：{}({})，字段{}校验失败，期望返回：{}，实际返回：{}". \
                                    format(proId_exp, pro['proName'], key, value, pro.get(key))
                                verification_res[key] = [False, exc_value]
                        elif displayInfo.get(key) is not None:
                            if value == displayInfo.get(key):
                                verification_res[key] = [True]
                            else:
                                exc_value = "促销：{}({})，字段{}校验失败，期望返回：{}，实际返回：{}". \
                                    format(proId_exp, pro['proName'], key, value, displayInfo.get(key))
                                verification_res[key] = [False, exc_value]
            verification_res_values = []
            for value in verification_res.values():
                verification_res_values.append(value[0])
            if False in verification_res_values:
                err = []
                for key, value in verification_res.items():
                    if False in value:
                        err.append(key)
                log_all.append({'error': '失败！！！促销：{}，存在校验失败字段，具体字段列表：{}'.format(proId_exp, err)})
            else:
                log_all.append(
                    {'info': '成功！促销：{}，所有字段值校验均正确：{}'.format(proId_exp, list(verification_res.keys()))})
            verification_res_all[proId_exp] = verification_res

        verification_res = {}
        if sorted(proIds_exp) == sorted(proIds):
            verification_res['促销列表校验结果'] = [True]
            log_all.append({'info': '正确命中所有期望命中的促销：{}'.format(proIds)})
        else:
            exc_value = '期望命中促销列表与实际命中促销列表不一致，期望命中促销：{},实际命中促销：{}'.format(
                sorted(proIds_exp), sorted(proIds))
            verification_res['促销列表校验结果'] = [False, exc_value]
        verification_res_all['促销列表校验结果'] = verification_res
        return verification_res_all, log_all

    def calc_result_check_price(self, result, res_exp={}):
        """
        只校验返回结果中的最终优惠金额以及应付金额
        线上线下算价通用
        orderTotalSettlePrice:订单的应付金额 即过了所有促销后的金额；
        totalOrigPrice:购物车/订单原始电商总价(以sku的单品促销价计算)；
        totalOrigPrice2:购物车/订单原始电商总价(以sku的单品原始计算)；
        otherCondProDiscountAmount:分类/品牌促销优惠金额；
        totalDiscountAmount:购物车/订单总优惠金额（条件+整单两个维度上的优惠金额）；
        totalDiscountAmount2:总优惠金额二(单品+条件+整单三个维度促销的优惠金额)；
        :param result:算价接口返回的原始算价结果
        :param res_exp:期望校验的字段以及对应值。格式：res_exp = {'orderTotalSettlePrice': 3100}
        """
        logger.info('\n')
        logger.info('================开始校验返回的实际应支付金额是否正确================')
        # 校验返回结果
        verification_res = {}
        for key in res_exp:
            if key in result:
                if res_exp[key] is not None:
                    verification_res[key] = (result[key] == res_exp[key],
                                             '促销最终计算结果，字段{}校验失败，期望返回：{}，实际返回：{}'.format(key,
                                                                                                              res_exp[
                                                                                                                  key],
                                                                                                              result[
                                                                                                                  key]))
                else:
                    pass
            # elif result['matchedStaffPros'] and result['matchedStaffPros'].get(key, None):     # 员工优惠金额在matchedStaffPro 节点下
            #     verification_res[key] = pytest.assume(result['matchedStaffPro'][key] == res_exp[key], '促销最终计算结果，字段{}校验失败，期望返回：{}，实际返回：{}'.format(key, res_exp[key], result['matchedStaffPro'][key]))
            else:
                verification_res[key] = (str(result.get('key')) == str(res_exp[key]),
                                         '促销最终计算结果，字段{}校验失败，期望返回：{}，实际未返回该字段'.format(key,
                                                                                                               res_exp[
                                                                                                                   key]))

        if False in verification_res.values():
            err = []
            for key, value in verification_res.items():
                if value is False:
                    err.append(key)
            logger.error('失败！！！促销最终计算结果，存在校验失败字段，具体字段列表：{}'.format(err))
        else:
            logger.info('成功！促销最终计算结果，所有字段值校验均正确：{}'.format(verification_res.keys()))


class OthersMethod:
    def yml_modify(self, data):
        """修改data文件夹中所有yml中的对应数据"""
        BASE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
        data_path = os.path.join(BASE_PATH, "data")
        files = []
        from pathlib import Path
        for p in Path(data_path).iterdir():
            if str(p)[-3:] == 'yml':
                files.append(p)
            else:
                files.extend(p.rglob('*.yml'))
        if data:
            for file in files:
                file = str(file)
                if file[-3:] == 'yml':
                    for pro_old, pro_new in data.items():
                        with open(file, 'r', encoding='utf-8') as f:
                            yml_content = f.read()
                        f.close()
                        if str(pro_old) in yml_content:
                            new_content = yml_content.replace(str(pro_old), str(pro_new))
                            with open(file, 'w+', encoding='utf-8') as f:
                                f.write(new_content)
                            f.close()
                            print('yml文件内容更新成功！yml文件：{}。更新前后促销id分别为：{}-->{}'.format(file, pro_old,
                                                                                                       pro_new))
        else:
            print('未复制任何促销，所以未修改任何yml文件内容。')

    def log_print(self, log_all):
        """日志打印"""
        for logs in log_all:
            for key, value in logs.items():
                if key == 'info':
                    logger.info(value)
                elif key == 'error':
                    logger.error(value)

    def docstring_parameter(*sub):
        """写一个可以添加变量注释的装饰器"""

        def dec(obj):
            obj.__doc__ = obj.__doc__.format(*sub)
            return obj

        return dec


class ProInfo:
    def __init__(self, address):
        self.address = address

    def pro_list_query_by_proid(self, ticket, pro_id):
        url = '{}/instance/page'.format(self.address)
        header = {"Cookie": "ticket={}".format(ticket), "Content-Type": "text/plain"}
        # print(header)
        data = {"proId": pro_id, "currentPage": 1, "pageSize": 10}
        data = json.dumps(data)
        res = requests.post(url, data=data, headers=header)
        res_code = res.json()['code']
        # print(res.text)
        if res_code == '0000':
            res_data = res.json()['data']
        print(res_data)
        return res_data

    def pro_view(self, ticket, pro_id):
        """调用来客查询促销详情接口，返回促销相关信息"""
        url = '{}/instance/info/{}'.format(self.address, pro_id)
        header = {"Cookie": "ticket={}".format(ticket)}
        # print(header)
        # print(url)
        res = requests.get(url, headers=header)
        # print(res.encoding)
        res_code = res.json()['code']
        # print(res.text.encode("ISO-8859-1").decode('utf8'))
        if res_code == '0000':
            res_data = json.loads(res.text)['data']
            # print('--------------------')
        else:
            raise Exception('调用url返回错误：{}'.format(res.text))
        # 处理一下促销类型
        res_data['baseInfo']['proType'] = pro_type[res_data['baseInfo']['proType']]
        print('查询到的促销详情为：', res_data)
        return res_data

    def pro_copy(self, ticket, pro_id):
        """先调用查询促销详情接口，获取促销内容，然后创建一个配置项一样的促销"""
        pro_info = self.pro_view(ticket, pro_id)
        url = '{}/instance/save'.format(self.address, pro_id)
        header = {"Cookie": "ticket={}".format(ticket), "Content-Type": "text/plain"}
        # print(header)
        # print(url)
        # 处理一下促销类型
        for k, v in pro_type.items():
            if pro_info['baseInfo']['proType'] == v:
                pro_info['baseInfo']['proType'] = k
                break
        # 为了避免复制之前的促销是已过期的。所以重新设置促销时间
        proStartTime = datetime.datetime.now().strftime("%Y-%m-%d") + ' 00:00:00'
        proEndTime = (datetime.datetime.now() + datetime.timedelta(days=360)).strftime("%Y-%m-%d") + ' 00:00:00'
        # 处理joinItem，适应全部商品
        joinItem = pro_info.get('joinItem', None)
        if joinItem:
            items = joinItem.get('singleItems')[0].get('items')
            if items == [{}]:
                joinItem['singleItems'][0]['items'] = None
        # 构建入参
        data = {
            "barCode": pro_info.get('barCode', None),
            "baseInfo": pro_info.get('baseInfo', None),
            "blackList": pro_info.get('blackList', None),
            "channel": pro_info.get('channel', None),
            "excludeItems": pro_info.get('excludeItems', []),
            "expenseRules": pro_info.get('expenseRules', []),
            "joinExecutor": pro_info.get('joinExecutor', None),
            "joinItem": pro_info.get('joinItem', None),
            "member": pro_info.get('member', None),
            "printing": pro_info.get('printing', None),
            "rule": pro_info.get('rule', None),
            "suitTriggers": pro_info.get('suitTriggers', []),
            "suitReward": pro_info.get('suitReward', None),  # 组合促销必填
            "time": {
                "dateType": pro_info['time'].get('dateType', 0),
                "execTimes": pro_info['time'].get('execTimes', []),
                "proEndTime": proEndTime,
                "proStartTime": proStartTime
            },
            "venderBaseInfo": pro_info.get('venderBaseInfo', None),
            "cashierRule": pro_info.get('cashierRule', None),
            "showInfo": pro_info.get('showInfo', None)
        }
        # 如果是整单促销，不需要促销商品joinItem
        if pro_info.get('baseInfo').get('proType') == 9:
            data['joinItem'] = None
        data = json.dumps(data)
        print('复制促销入参为：', data)
        res = requests.post(url, data=data, headers=header)
        res_code = res.json()['code']
        if res_code == '0000':
            pro_id_copy = json.loads(res.text)['data']
            print('促销复制成功，原促销id为：{}，复制后促销id为：{}'.format(pro_id, pro_id_copy))
        else:
            pro_id_copy = None
            print('促销复制失败，促销id为：{}，报错信息为：{}'.format(pro_id, res.text))
            pytest.assume(False, '处理的促销id：{}，调用url返回错误：{}'.format(pro_id, res.text))
        return pro_id_copy

    # def pro_status_not_4(self, ticket, db_info, pro_ids):
    #     """传入促销id列表，返回不为促销中的数据，如果为已结束或强制结束就重新新建促销"""
    #     mysql_query = MysqlQuery(db_info)
    #     pros = mysql_query.pro_status_view(pro_ids)
    #     pro_ids_copy = {}
    #     pro_copy_fail = []
    #     for pro_id, status in pros.items():
    #         if status in (5, 7):
    #             pro_id_copy = self.pro_copy(ticket, pro_id)
    #             if pro_id_copy is not None:
    #                 pro_ids_copy[pro_id] = pro_id_copy
    #             else:
    #                 pro_copy_fail.append(pro_id)
    #         elif status == 3:
    #             print('部分促销状态为审核通过，如：{}，需要等待其变更为促销中！！'.format(pro_id))
    #             pro_ids_copy[pro_id] = pro_id
    #         elif status == 4:
    #             pass
    #         else:
    #             pytest.assume(False, '处理的促销id：{}，查询到的促销状态为：{}。理论上不应该，不合理，检查一下吧~~~~~'.format(pro_id, status))
    #     if pro_copy_fail:
    #         print('复制失败的促销列表：{}'.format(pro_copy_fail))
    #     if pro_ids_copy:
    #         pass
    #     else:
    #         print('所有促销状态正常，没有需要重新创建的数据！')
    #     mysql_query.mydb.close()
    #     return pro_ids_copy

    def pro_status_not_4(self, ticket, db_info, pro_ids):
        """传入促销id列表，返回不为促销中的数据，如果为已结束或强制结束就重新新建促销"""
        pro_ids_copy = {}
        for ids in pro_ids:
            pro_ids_copy[ids] = 4
        # mysql_query = MysqlQuery(db_info)
        # pros = mysql_query.pro_status_view(pro_ids)
        pros = {}
        res = []
        for ids in pro_ids:
            res.append((ids, 4))
        for re in res:
            pros[re[0]] = re[1]
        # pro_ids_copy = {}
        pro_copy_fail = []
        for pro_id, status in pros.items():
            if status in (5, 7):
                pro_id_copy = self.pro_copy(ticket, pro_id)
                if pro_id_copy is not None:
                    pro_ids_copy[pro_id] = pro_id_copy
                else:
                    pro_copy_fail.append(pro_id)
            elif status == 3:
                print('部分促销状态为审核通过，如：{}，需要等待其变更为促销中！！'.format(pro_id))
                pro_ids_copy[pro_id] = pro_id
            elif status == 4:
                pass
            else:
                pytest.assume(False,
                              '处理的促销id：{}，查询到的促销状态为：{}。理论上不应该，不合理，检查一下吧~~~~~'.format(pro_id,
                                                                                                                 status))
        if pro_copy_fail:
            print('复制失败的促销列表：{}'.format(pro_copy_fail))
        if pro_ids_copy:
            pass
        else:
            print('所有促销状态正常，没有需要重新创建的数据！')
        # mysql_query.mydb.close()
        return pro_ids_copy


class OfflineCalc:

    def __init__(self, **kwargs):
        """
        初始化数据

        :param data:yml文件中的完整测试数据。传入之后，再取需要的字段进行处理
        """
        self.ware_data = kwargs['ware_data']
        # self.staffPromoCalcPara = data.get('staffPromoCalcPara', None)
        # self.others_data = data.get('others_data', {})  # 接口入参中除了skus之外的其他字段
        self.data = kwargs  # 便于取测试数据中除了入参之外的其他数据，比如cookies中的language
        # self.language = self.data.get('language', 'zh_HK')  # 因为校验促销语的时候，需要取对应语言的促销语进行校验，所以需要把语言放在最上面
        self.exp_results = kwargs.get('exp_results', False)  # 是否存在多个期望结果的标识。针对bestoffer促销可能存在多种正确的结果
        # self.env_hosts, self.env_others = get_env['env_hosts'], get_env['env_others']
        self.othersMethod = OthersMethod()
        self.common = Common()
        # self.channel_data = self.others_data.get('channel', "POS") if self.others_data.get('channel',
        #                                                                                    "POS") != "" else "POS"  # 平台
        # self.userType_data = self.others_data.get('userType', []) if self.others_data.get('userType',
        #                                                                                   []) != [] else None  # 会员类型
        # self.dEnv = self.others_data.get('dEnv', '')
        # # self.dEnv = "dEnv-test=gray04"
        # # UMO回滚需求，修改barCodeList中的数据类型为str
        # barCodeList_str = []
        # for barCodeList in self.others_data.get('barCodeList', []):
        #     barCodeList_str.append(str(barCodeList))
        # self.others_data['barCodeList'] = barCodeList_str
        #
        # # 设置是否离线标识
        # self.offline_flag = False
        pass

    def result_separate(self, result):
        """
        接口结果分解
        :param result:算价接口返回的原始算价结果
        :return:分解结果：{'pros': pros_sort, 'shares': skus_share_info}
        """

        pros = []
        skus_share_info = []
        skus_info = []

        items = result['items']
        # 校验条件、单品、买赠促销
        for item in items:

            if item['group'] is False:  # 2.0默认不分组
                # 校验单品促销
                singleSkuItem = item['singleSkuItem']
                skus_info.append(singleSkuItem)
                if singleSkuItem.get('matchedSinglePro'):
                    matchedSinglePro = singleSkuItem['matchedSinglePro']  # 单品促销数据
                    try:
                        proDicount = matchedSinglePro['proDicount']  # 商品总优惠额=单个优惠额*商品个数
                        # totalOrigPrice = sku['totalOrigPrice']  # 原始总价
                        # totalProPrice = sku['totalProPrice']  # 享受单品促销后的促销总价
                        # totalSettlePrice = sku['totalSettlePrice']  # 商品行分摊后的总价？？？
                        pro = matchedSinglePro
                        pro['skuDiscount'] = None
                        pros.append(pro)
                    except:
                        pytest.assume(False, 'matchedSinglePro结构错误：{}'.format(singleSkuItem))

                # 取出每个sku的分摊数据
                if singleSkuItem.get('skuProShareInfoList'):
                    share_info = self.__sku_share(singleSkuItem)
                    skus_share_info.extend(share_info)
                else:  # 如果该主品没有参与任何促销
                    try:
                        share_info = {'sku': singleSkuItem['skuId'], 'sku_type': singleSkuItem['skuType'],
                                      'price': singleSkuItem['origPrice'], 'num': singleSkuItem['packNum'], 'proId': 0,
                                      'shareDiscount': 0, 'afterSharePrice': 0,
                                      'unitProPrice': singleSkuItem['unitProPrice']}
                        skus_share_info.append(share_info)
                    except KeyError:
                        pytest.assume(False, 'items中存在结构错误的singleSkuItem：{}'.format(singleSkuItem))
                        pass

        # 校验满件、满额、买中买、组合、换购、分类、品牌促銷
        matchedCondPros = result['matchedCondPros']
        for matchedCondPro in matchedCondPros:
            proDicount = matchedCondPro['proDicount']
            giftGoods = matchedCondPro.get('giftGoods', {})
            if giftGoods is None:
                choosedGiftSkus = []
            else:
                choosedGiftSkus = giftGoods.get('selectedGiftSkus', [])
                if choosedGiftSkus is None:
                    choosedGiftSkus = []
            tradeGoods = matchedCondPro.get('tradeGoods', {})
            if tradeGoods is None:
                choosedTradeSkus = []
            else:
                choosedTradeSkus = tradeGoods.get('selectedTradeSkus', [])
                if choosedTradeSkus is None:
                    choosedTradeSkus = []
            skuDiscount = 0
            for choosedGiftSku in choosedGiftSkus:  # 如果存在赠品数据，就取出对应的分摊信息
                share_info = self.__sku_share(choosedGiftSku, sku_type='GIFT_SKU', proId_in=matchedCondPro['proId'])
                skus_share_info.extend(share_info)
                skuDiscount = proDicount
            for choosedTradeSku in choosedTradeSkus:  # 如果存在换购品数据，就取出对应的分摊信息
                share_info = self.__sku_share(choosedTradeSku, sku_type='TRADE_SKU', proId_in=matchedCondPro['proId'])
                skus_share_info.extend(share_info)
                skuDiscount = proDicount
            if len(choosedGiftSkus) == 0 and len(choosedTradeSkus) == 0:
                skuDiscount = None
            pro = matchedCondPro
            pro['skuDiscount'] = skuDiscount
            pro['choosedGiftSkus'] = choosedGiftSkus
            pro['choosedTradeSkus'] = choosedTradeSkus
            pros.append(pro)

        # 校验整单促销，线下整单要考虑折扣和满减
        if result.get('matchedOrderPro'):
            matchedOrderPro = result['matchedOrderPro']
            proId = matchedOrderPro['proId']
            proDicount = matchedOrderPro.get('proDicount')
            giftGoods = matchedOrderPro.get('giftGoods', {})
            if giftGoods is None:
                choosedGiftSkus = []
            else:
                choosedGiftSkus = giftGoods.get('selectedGiftSkus', [])
                if choosedGiftSkus is None:
                    choosedGiftSkus = []
            tradeGoods = matchedOrderPro.get('tradeGoods', {})
            if tradeGoods is None:
                choosedTradeSkus = []
            else:
                choosedTradeSkus = tradeGoods.get('selectedTradeSkus', [])
                if choosedTradeSkus is None:
                    choosedTradeSkus = []
            skuDiscount = 0
            for choosedGiftSku in choosedGiftSkus:  # 如果存在赠品数据，就取出对应的分摊信息
                share_info = self.__sku_share(choosedGiftSku, sku_type='GIFT_SKU', proId_in=proId)
                skus_share_info.extend(share_info)
                skuDiscount = proDicount
            for choosedTradeSku in choosedTradeSkus:  # 如果存在换购品数据，就取出对应的分摊信息
                share_info = self.__sku_share(choosedTradeSku, sku_type='TRADE_SKU', proId_in=proId)
                skus_share_info.extend(share_info)
                skuDiscount = proDicount
            if len(choosedTradeSkus) == 0 and len(choosedGiftSkus) == 0:
                skuDiscount = None
            pro = matchedOrderPro
            pro['skuDiscount'] = skuDiscount
            pro['choosedGiftSkus'] = choosedGiftSkus
            pro['choosedTradeSkus'] = choosedTradeSkus
            pros.append(pro)

        # 校验员工优惠，只有折扣
        if result.get('matchedStaffPros'):
            for matchedStaffPro in result['matchedStaffPros']:
                proId = matchedStaffPro['proId']
                proDicount = matchedStaffPro.get('proDicount')
                # 员工优惠-优惠金额
                staffDeductionAmount = matchedStaffPro.get('staffDeductionAmount')
                # 员工优惠-折扣值（小数）
                staffRebate = matchedStaffPro.get('staffRebate')
                giftGoods = matchedStaffPro.get('giftGoods', {})
                if giftGoods is None:
                    choosedGiftSkus = []
                else:
                    choosedGiftSkus = giftGoods.get('selectedGiftSkus', [])
                    if choosedGiftSkus is None:
                        choosedGiftSkus = []
                tradeGoods = matchedStaffPro.get('tradeGoods', {})
                if tradeGoods is None:
                    choosedTradeSkus = []
                else:
                    choosedTradeSkus = tradeGoods.get('selectedTradeSkus', [])
                    if choosedTradeSkus is None:
                        choosedTradeSkus = []
                skuDiscount = 0
                for choosedGiftSku in choosedGiftSkus:  # 如果存在赠品数据，就取出对应的分摊信息
                    share_info = self.__sku_share(choosedGiftSku, sku_type='GIFT_SKU', proId_in=proId)
                    skus_share_info.extend(share_info)
                    skuDiscount = proDicount
                for choosedTradeSku in choosedTradeSkus:  # 如果存在换购品数据，就取出对应的分摊信息
                    share_info = self.__sku_share(choosedTradeSku, sku_type='TRADE_SKU', proId_in=proId)
                    skus_share_info.extend(share_info)
                    skuDiscount = proDicount
                if len(choosedTradeSkus) == 0 and len(choosedGiftSkus) == 0:
                    skuDiscount = None
                pro = matchedStaffPro
                pro['skuDiscount'] = skuDiscount
                pro['staffDeductionAmount'] = staffDeductionAmount
                pro['staffRebate'] = staffRebate
                pro['choosedGiftSkus'] = choosedGiftSkus
                pro['choosedTradeSkus'] = choosedTradeSkus
                pros.append(pro)

        # 处理赠品和换购品中可能存在的单品促销
        for pro in pros:
            if pro.get('choosedGiftSkus'):
                for choosedGiftSku in pro.get('choosedGiftSkus'):
                    skus_info.append(choosedGiftSku)
                    if choosedGiftSku.get('matchedSinglePro'):
                        matchedSinglePro = choosedGiftSku['matchedSinglePro']  # 单品促销数据
                        try:
                            proDicount = matchedSinglePro['proDicount']  # 商品总优惠额=单个优惠额*商品个数
                            pro = matchedSinglePro
                            pro['skuDiscount'] = None
                            pros.append(pro)
                        except:
                            pytest.assume(False, 'matchedSinglePro结构错误：{}'.format(choosedGiftSku))
            if pro.get('choosedTradeSkus'):
                for choosedTradeSku in pro.get('choosedTradeSkus'):
                    skus_info.append(choosedTradeSku)
                    if choosedTradeSku.get('matchedSinglePro'):
                        matchedSinglePro = choosedTradeSku['matchedSinglePro']  # 单品促销数据
                        try:
                            proDicount = matchedSinglePro['proDicount']  # 商品总优惠额=单个优惠额*商品个数
                            pro = matchedSinglePro
                            pro['skuDiscount'] = None
                            pros.append(pro)
                        except:
                            pytest.assume(False, 'matchedSinglePro结构错误：{}'.format(choosedTradeSku))

        # 给pros按照计算顺序排序！
        pros_sort = []
        # bestoffer多个促销单独分摊，那么这个顺序要处理吗
        pro_type = {1: 'UNIT', 2: 'AMOUNT', 3: 'QUANTITY', 4: 'PWP', 5: 'MATCH', 6: 'REDEEM', 7: 'BRAND', 8: 'CATE',
                    9: 'BASKET', 10: 'SPECIAL_IDENTITY', 11: 'PAYMENT', 12: 'PAYMENT_FREEBIE', 14: 'STAFF'}
        for type in pro_type.values():
            for p in pros:
                if p['proType'] == type:
                    pros_sort.append(p)
                    continue

        logger.info('命中的所有促销为：{}'.format(pros_sort))
        logger.info('所有商品的分摊数据为：{}'.format(skus_share_info))
        logger.info('所有的商品详情为：{}'.format(skus_info))

        ret = {'pros': pros_sort, 'shares': skus_share_info, 'skus_info': skus_info}
        return ret

    def __sku_share(self, sku_info, sku_type='MAIN_SKU', proId_in=0):
        """proId_in: 因为换购品可以参与后续的整单促销，需要记录这是哪个促销的换购品"""
        share_infos = []
        sku_share_info = sku_info['skuProShareInfoList']
        if sku_info.get('unitProPrice') is not None:
            unitProPrice = sku_info['unitProPrice']
        else:
            unitProPrice = sku_info['origPrice']
            # pytest.assume(False, '当前sku_info中不包含unitProPrice，请检查。具体信息为：{}'.format(sku_info))
        if sku_type == 'MAIN_SKU':
            num = sku_info['packNum']
        else:
            num = sku_info['rewardQty']
        for share in sku_share_info:
            proId = share['proId']  # 参与当前分摊的促销id
            shareDiscount = share['shareDiscount']
            afterSharePrice = share['afterSharePrice']
            if sku_type == 'MAIN_SKU':
                averageProPrice = 0
            else:
                averageProPrice = sku_info['averageProPrice']
            share_info = {'sku': sku_info['skuId'], 'sku_type': sku_type, 'price': sku_info['origPrice'], 'num': num,
                          'proId': proId, 'proId_in': proId_in, 'shareDiscount': shareDiscount,
                          'afterSharePrice': afterSharePrice, 'unitProPrice': unitProPrice,
                          'uniqueId': sku_info['uniqueId'],
                          'averageProPrice': averageProPrice}
            share_infos.append(share_info)
        return share_infos

    def result_check(self, res_original, res_separate, exps, cashierAlerts_flag=True):
        """根据exp_results来判断是否有多个合理的结果，如果有，则exps中会存在多个列表，如果没有，则直接将exps传入调用具体的校验方法"""
        if not isinstance(self.exp_results, bool):
            # 避免exp_results出现错误的值
            raise Exception('exp_results期望为布尔值（True或者False），实际传入：{}！'.format(self.exp_results))
        if self.exp_results is False:
            res, log_all = self.__result_check_all(res_original, res_separate, exps, cashierAlerts_flag)
            for exc in res.values():
                for e in exc.values():
                    if not isinstance(e, list):  # 针对员工优惠做的特殊判断
                        exc_values = e.values()
                        for exc_value in exc_values:
                            if exc_value[0] is False:
                                assert False, '{}'.format(exc_value[1])
                    else:
                        if e[0] is True:
                            assert False, '{}'.format(e[1])
            self.othersMethod.log_print(log_all)
        elif self.exp_results is True:
            logger.info('\n')
            logger.info('================exp_results is True!!!开始循环校验proInfo_exp================')
            for exp in exps:
                logger.info('当前校验的proInfo_exp为：{}'.format(exp))
                res, log_all = self.__result_check_all(res_original, res_separate, exp, cashierAlerts_flag)
                exc_values = []
                for exc in res.values():
                    for e in exc.values():
                        exc_value = e.values()
                        for value in exc_value:
                            exc_values.extend(list(value))
                # 如果存在一条结果全部为true，说明这条期望结果与实际结果一致。退出循环并打印对应日志
                if False not in exc_values:
                    logger.info('正确的proInfo_exp为：{}'.format(exp))
                    self.othersMethod.log_print(log_all)
                    break
            # 如果正常退出循环，说明所有期望结果都与实际结果不一致，那么打印最后一个期望值对应的错误信息和日志
            else:
                if exps:
                    for exc in res.values():
                        for e in exc.values():
                            exc_values = e.values()
                            for exc_value in exc_values:
                                if exc_value[0] is False:
                                    pytest.assume(False, '{}'.format(exc_value[1]))
                    self.othersMethod.log_print(log_all)
                    logger.error('所有期望结果均校验失败！！！')
                else:
                    logger.info('期望命中促销为空，不存在分摊数据。')

    def __result_check_all(self, res_original, res_separate, exps, cashierAlerts_flag=True):
        """调用各个校验结果方法，并将所有的结果拼接"""
        res_proinfo, log_all_proinfo = self.common.calc_result_check_proinfo_list(res_separate, exps)
        res_proId_skus, log_all_proId_skus = self.__result_check_proId_skus(res_separate, exps)
        res_shares_by_exp, log_all1_shares_by_exp = self.__result_check_shares_by_exp(res_separate, exps)
        res_shares, log_all_shares = self.__result_check_shares(res_separate, exps)
        res_skus_info, log_all_skus_info = self.__result_check_skus_info(res_separate)
        res_staff, log_all_staff = self.__result_check_staff(res_separate, exps)
        # res_paperCouponResults, log_all_paperCouponResults = self.__result_check_paperCouponResults(ticket,
        #                                                                                             res_original)
        # res_proSkuEnjoyInfos, log_all_proSkuEnjoyInfos = self.__result_check_proSkuEnjoyInfos(ticket, res_original)
        # if cashierAlerts_flag:
        #     res_cashierAlerts, log_all_cashierAlerts = self.__result_check_cashierAlerts(ticket, res_original)
        # else:
        #     res_cashierAlerts, log_all_cashierAlerts = {}, []
        res_total_price, log_all_total_price = self.__check_total_price(res_original, res_separate, exps)
        res_all = {'res_proinfo': res_proinfo, 'res_proId_skus': res_proId_skus, 'res_shares_by_exp': res_shares_by_exp,
                   'res_shares': res_shares, 'res_skus_info': res_skus_info, 'res_staff': res_staff,
                   'res_total_price': res_total_price}
        logger.info('该proInfo_exp对应的校验结果为：{}'.format(res_all))
        log_all = log_all1_shares_by_exp + log_all_shares + log_all_proinfo + log_all_proId_skus + log_all_skus_info + log_all_staff + log_all_total_price
        return res_all, log_all

    def __result_check_staff(self, res_separate, exps=[]):
        """
        算价结果中，员工优惠信息
        """
        verification_staff = {}
        log_all = [{'info': '\n'},
                   {'info': '================开始校验返回的员工优惠金额================'}]
        staff_verification_key = ['afterSaleStaffBalance', 'staffDeductionAmount', 'overflowAmount']
        for exp in exps:
            for staff_key in staff_verification_key:
                if staff_key in exp:
                    for key, value in exp.items():
                        if key == staff_key:
                            for pro in res_separate['pros']:
                                if pro.get(key, None) is not None:
                                    if pro[key] != value:
                                        exc_value = '字段{}，期望与实际值不一致，期望值为：{}，实际为：{}'.format(key, value,
                                                                                                             pro[key])
                                        verification_staff[key] = [False, exc_value]
                                        log_all.append({'error': exc_value})
                                    else:
                                        verification_staff[key] = [True]
                                        log_all.append(
                                            {'info': '字段{}，校验通过。期望值为：{}。'.format(key, value)})
                                    break
        return verification_staff, log_all

    def __result_check_shares(self, res_separate, exps=[]):
        """
        算价结果中的商品分摊校验

        :param res_separate:分解后的算价结果。格式：{'pros': pros_sort, 'shares': skus_share_info}
        :param exps:期望命中的促销列表，格式：exp = [{'proId_exp': 2021030500000881, 'proSlogan': 'XX', 'showSlogan': 'XX'}]
        :return:
        """

        pros = res_separate['pros']
        shares = res_separate['shares']
        verification_res_all = {}
        log_all = [{'info': '\n'}, {'info': '================开始校验分摊是否正确================'}]

        '''
        因为提前给所有促销按照计算顺序排了序
        所以可以直接用，pros来做循环一次计算分摊顺序'''
        main_skus = []  # 用来存储上一次循环结果中的sku,结构：{'sku': 'sku_type'}
        main_skus_in = []  # 用来存储上一次循环结果中的sku及其参与的促销,结构：{'sku': 'proId_in'}
        for pro in pros:
            verification_res = {}
            log_all.append({'info': '----------------当前促销信息为：----------------------\n{}'.format(pro)})

            # 如果传入了shares_exp，就不再自动计算分摊，直接根据期望值来校验
            shares_exp_flag = False
            for pro_exp in exps:
                if pro_exp['proId_exp'] == pro['proId']:
                    if pro_exp.get('shares_exp') is not None:
                        shares_exp_flag = True
                        break
            if shares_exp_flag is True:
                log_all.append({
                    'info': '当前促销({})传入了shares_exp，所以不再自动计算分摊，直接根据期望值来校验。'.format(
                        pro['proId'])})
                continue

            # 简单校验一下，每个促销的分摊金额之和应该与该促销总优惠金额一致
            totalDiscount = 0
            for share in shares:
                if share['proId'] != pro['proId']:
                    continue
                totalDiscount = totalDiscount + share['shareDiscount']
            if pro['proDicount'] is not None and pro['skuDiscount'] is None:  # 如果不是赠品/换购
                if int(totalDiscount) == int(pro['proDicount']):
                    verification_res['分摊金额之和与该促销总优惠金额一致'] = [True]
                else:
                    exc_value = '促销id：{}({})，中的促销的分摊金额之和{}!=该促销总优惠金额proDicount{}!!!这会导致计算出来的期望分摊结果错误。'.format(
                        pro['proId'], pro['proName'], totalDiscount, pro['proDicount'])
                    verification_res['分摊金额之和与该促销总优惠金额一致'] = [False, exc_value]
            elif pro['skuDiscount'] is not None:  # 如果是赠品/换购
                if int(totalDiscount) == int(pro['skuDiscount']):
                    verification_res['skuDiscount'] = [True]
                else:
                    exc_value = '促销id：{}({})，中的促销的分摊金额之和{}!=该促销总优惠金额skuDiscount{}!!!这会导致计算出来的期望分摊结果错误。'.format(
                        pro['proId'], pro['proName'], totalDiscount, pro['skuDiscount'])
                    verification_res['skuDiscount'] = [False, exc_value]

            # 按顺序计算分摊后价格
            """需要考虑的情况：
            1.如果是普通促销的主品，那么所有促销类型主品一起分摊，那么价格只用计算一次就行
            2.如果是跟组合叠加，那么商品组会分成两部分，一部分A参与组合促销并分摊，一部分B参与其他促销并分摊，此时需要将A+B
              PS：这种情况暂时未考虑，毕竟太少见而且逻辑复杂容易出错，如果出现，建议还是手工测试
            3.如果是赠品/换购品，可能存在一个sku，类型为赠品，分别参与多个促销的情况。
            4.因为是按顺序分摊的，所以如果一个商品在前面已经参与过别的促销，那么计算下一个促销时的商品总金额，要用商品上一次促销享受后的价格"""
            # 取出实际每个促销的优惠金额
            if pro['enjoyProTimes'] <= 0:  # 说明该促销是命中但是未享受
                log_all.append({'info': '该促销命中但是未享受，促销id：{}({})'.format(pro['proId'], pro['proName'])})
                # 如果是命中未享受，就不应该存在分摊数据
                for s in shares:
                    if s['proId'] != pro['proId']:
                        verification_res['促销未享受但却存在分摊数据'] = [True]
                    else:
                        exc_value = '该促销enjoyProTimes为0，那么不应该存在分摊数据，实际存在分摊，请检查！！！促销id：{}({})'.format(
                            pro['proId'],
                            pro['proName'])
                        verification_res['促销未享受但却存在分摊数据'] = [False, exc_value]
                        break
                verification_res_all[pro['proId']] = verification_res
                continue
            elif pro['skuDiscount'] is not None:
                discount = pro['skuDiscount']  # 取出该促销的实际优惠金额
                log_all.append({'info': '促销：{}，当前促销子类型为赠品或者换购，优惠金额只分摊到赠品或者换购品上！'.format(
                    pro['proId'])})
            else:
                discount = pro['proDicount']  # 取出该促销的实际优惠金额

            # 先计算出每个促销对应的商品总金额
            afterSharePrice = None
            sku_totalPrice = {}
            for s in shares:
                # print('当前分摊信息为：', s)
                # print('当前main_sku为：', main_skus)
                # print('当前main_sku_in为：', main_skus_in)
                # print('当前afterSharePrice为：', afterSharePrice)
                # proId为0，说明该商品没有参与任何促销
                if s['proId'] == 0:
                    log_all.append(
                        {'info': '该商品没有命中任何促销，不参与分摊计算！{}__{}'.format(s['sku'], s['sku_type'])})
                    continue
                # 判断是否是第一次分摊。如果sku和sku_type存在，但是促销id却并不是这次的，且proId_in与上一次一致，说明这个sku之前分摊过
                elif s['proId'] != pro['proId'] and {s['sku']: s['sku_type']} in main_skus:
                    # print('该sku：{}已经计算过一次分摊，本次应该取分摊后的价格:{}来计算'.format(s['sku'], s['afterSharePrice']))
                    afterSharePrice = s['afterSharePrice']
                # 如果促销id相等，那么说明这个商品在享受了该促销，则取出该商品的总金额
                elif s['proId'] == pro['proId']:
                    # 避免作为赠品/换购品参与多个促销时，前序判断会导致afterSharePrice有值
                    if {s['sku']: s['proId_in']} not in main_skus_in:
                        afterSharePrice = None
                    # 如果这个sku是之前分摊过的
                    if {s['sku']: s['sku_type']} in main_skus and afterSharePrice is not None:
                        # print('afterSharePrice不为None，说明这是该sku已经计算过分摊，本次应该取分摊后的价格来计算')
                        sku_price = afterSharePrice
                        sku_totalPrice.setdefault('{}__{}__{}'.format(s['sku'], s['sku_type'], s['proId_in']),
                                                  sku_price)
                        # print('===对于促销:{},商品与其参与分摊的总价格为：{}'.format(pro['proId'], sku_totalPrice))
                        sku_price = None
                        afterSharePrice = None
                    # 如果这个sku之前没有分摊过
                    elif {s['sku']: s['sku_type']} not in main_skus:
                        main_skus.append({s['sku']: s['sku_type']})
                        main_skus_in.append({s['sku']: s['proId_in']})
                        # print('该sku是主品，且第一次进行分摊操作，应该用原价乘以个数')
                        sku_price = s['price'] * s['num']  # 无论是主品还是赠品，主要没有参与过其他促销的分摊，都应该用原价乘以个数来分摊
                        sku_totalPrice.setdefault('{}__{}__{}'.format(s['sku'], s['sku_type'], s['proId_in']),
                                                  sku_price)
                        # print('===对于促销:{},商品与其参与分摊的总价格为：{}'.format(pro['proId'], sku_totalPrice))
                        sku_price = None
                        afterSharePrice = None
                    elif {s['sku']: s['sku_type']} in main_skus and afterSharePrice is None:
                        # print('说明该sku该类型为赠品/换购品，购买了多个，且部分分别作为不同促销的赠品/换购品。或者一个sku对应多个uniqueId')
                        sku_price = s['price'] * s['num']
                        sku_totalPrice.setdefault(
                            '{}__{}__{}__{}__{}'.format(s['sku'], s['sku_type'], s['proId_in'], pro['proId'],
                                                        s['uniqueId']), sku_price)
                        # print('===对于促销:{},商品与其参与分摊的总价格为：{}'.format(pro['proId'], sku_totalPrice))
                        sku_price = None
                        afterSharePrice = None
                    else:
                        raise Exception(
                            '促销：{}({})，按理来说不应该有数据走到这里来，检查一下：{}/{}/{}'.format(pro['proId'],
                                                                                                  pro['proName'],
                                                                                                  s['sku'],
                                                                                                  s['sku_type'],
                                                                                                  afterSharePrice))
                else:
                    pass

            log_all.append({'info': '对于促销:{},商品与其参与分摊的总价格为：{}'.format(pro['proId'], sku_totalPrice)})
            log_all.append({'info': '对于促销:{},优惠总金额为：{}'.format(pro['proId'], discount)})
            # 总金额
            count = len(sku_totalPrice)
            totalPrice = 0
            modify_flag = False
            for ss in sku_totalPrice:
                value = sku_totalPrice[ss]
                # bestoffer需要指定每个sku用于分摊的商品数量。需要从期望结果中获取
                for pro_exp in exps:
                    if pro_exp['proId_exp'] == pro['proId']:
                        skus_exp = pro_exp.get('skus_exp', [])
                        if isinstance(skus_exp, list):
                            break
                        elif isinstance(skus_exp, dict):
                            # 获取每个sku上一次优惠后的均价avg_price，目前在bestoffer前面只有单品促销，所以只用取单品促销价
                            for share in shares:
                                if share['sku'] == int(ss.split('__')[0]):
                                    avg_price = share['unitProPrice']
                                    if skus_exp.get(share['sku']):
                                        value = avg_price * skus_exp[share['sku']]
                                        sku_totalPrice[ss] = value
                                        modify_flag = True
                                    else:
                                        exc_value = '对于促销：{}({})，skus_exp不存在sku：{}'.format(pro['proId'],
                                                                                                  pro['proName'],
                                                                                                  share['sku'])
                                        verification_res['avg_price'] = [False, exc_value]
                                        log_all.append(
                                            {'error': '对于促销：{}({})，skus_exp不存在sku：{}'.format(pro['proId'],
                                                                                                    pro['proName'],
                                                                                                    share['sku'])})
                                    break
                        else:
                            raise Exception('促销：{}({})，skus_exp格式不正确，期望为列表或者字典！！！'.format(pro['proId'],
                                                                                                          pro[
                                                                                                              'proName']))
                if pro['skuDiscount'] is not None:  # 说明是赠品或者换购
                    sku_type = ss.split('__')[1]
                    if sku_type != 'MAIN_SKU' and int(ss.split('__')[2]) == pro['proId']:
                        totalPrice += value
                else:
                    totalPrice += value
            if modify_flag:
                log_all.append(
                    {'info': '对于促销:{},修改后的商品与其参与分摊的总价格为：{}'.format(pro['proId'], sku_totalPrice)})
            # 计算出该促销期望的分摊数据
            c = 0
            res = 0
            l = 0
            shares_exp = {}
            for sku in sku_totalPrice:
                ind = list(sku_totalPrice).index(sku)
                if pro['skuDiscount'] is not None:  # 说明是赠品或者换购
                    sku_type = sku.split('__')[1]
                    if sku_type != 'MAIN_SKU' and int(sku.split('__')[2]) == pro['proId']:
                        c += 1
                        if c < count:
                            if totalPrice != 0:
                                share_exp = sku_totalPrice[sku] * (
                                        discount / totalPrice)  # 还是要经过计算，避免后续出现多个赠品/换购品时计算不正确
                                share_exp = round(share_exp)
                                # 如果后续的totalPrice均为0，那么本次就就要用减法
                                follow_up = []
                                for i in sku_totalPrice:
                                    ind_now = list(sku_totalPrice).index(i)
                                    if ind_now <= ind:
                                        continue
                                    else:
                                        follow_up.append(sku_totalPrice[i])
                                if follow_up.count(0) == len(follow_up):
                                    share_exp = discount - res
                                # 如果分摊超过了总额，那么本次就使用减法
                                res += share_exp
                                if res > discount:
                                    res -= round(sku_totalPrice[sku] * (discount / totalPrice))
                                    share_exp = discount - res
                            else:
                                if pro['skuDiscount'] == 0:
                                    # 整单促销，赠品为0，还是可以正常享受促销。其他促销不行
                                    pass
                                else:
                                    log_all.append({
                                        'error': 'sku:{}对应的totalPrice为0。不应该存在这种情况出现！！！检查前序促销分摊之后的afterSharePrice是否为0。'.format(
                                            sku)})
                                    exc_value = '促销：{}({})，sku:{}对应的totalPrice为0。不应该存在这种情况出现！！！检查前序促销分摊之后的afterSharePrice是否为0。'.format(
                                        pro['proId'], pro['proName'], sku)
                                    verification_res['totalPrice'] = [False, exc_value]
                        else:
                            share_exp = discount - res
                            if share_exp < 0:
                                share_exp = 0
                    else:
                        share_exp = 0
                else:  # 除赠品和换购之外的其他促销分摊计算
                    c += 1
                    if c < count:
                        if totalPrice != 0:
                            share_exp = sku_totalPrice[sku] * (discount / totalPrice)
                            share_exp = round(share_exp)
                            # 如果后续的totalPrice均为0，那么本次就就要用减法
                            follow_up = []
                            for i in sku_totalPrice:
                                ind_now = list(sku_totalPrice).index(i)
                                if ind_now <= ind:
                                    continue
                                else:
                                    follow_up.append(sku_totalPrice[i])
                            if follow_up.count(0) == len(follow_up):
                                share_exp = discount - res
                            # 如果分摊超过了总额，那么本次就使用减法
                            res += share_exp
                            if res > discount:
                                res -= round(sku_totalPrice[sku] * (discount / totalPrice))
                                share_exp = discount - res
                        else:
                            log_all.append({
                                'error': 'sku:{}对应的totalPrice为0。不应该存在这种情况出现！！！检查前序促销分摊之后的afterSharePrice是否为0。'.format(
                                    sku)})
                            exc_value = '促销：{}({})，sku:{}对应的totalPrice为0。不应该存在这种情况出现！！！检查前序促销分摊之后的afterSharePrice是否为0。'.format(
                                pro['proId'], pro['proName'], sku)
                            verification_res['totalPrice'] = [False, exc_value]
                    else:
                        share_exp = discount - res
                        if share_exp < 0:
                            share_exp = 0
                log_all.append({'info': 'sku:{}, res:{}'.format(sku, share_exp)})
                shares_exp[sku] = share_exp
            shares_skus_res = {}
            for sku, share_exp in shares_exp.items():
                for share in shares:
                    if share['proId'] == pro['proId'] and share['sku'] == int(sku.split('__')[0]) and share[
                        'sku_type'] == sku.split('__')[1] and share['proId_in'] == int(sku.split('__')[2]):
                        # 添加校验，如果分摊存在负数，直接返回失败
                        if share['shareDiscount'] < 0:
                            exc_value = '促销id为：{}({})，商品sku为：{}，实际分摊结果中存在负数，校验不通过！期望分摊结果：{}，实际分摊结果：{}'.format(
                                pro['proId'], pro['proName'], sku, share_exp, share['shareDiscount'])
                            verification_res[sku] = [False, exc_value]
                            continue
                        # 没有负数，正常校验数据
                        if share_exp == share['shareDiscount']:
                            verification_res[sku] = [True]
                            shares_skus_res[sku] = [True]
                            log_all.append(
                                {'info': '正确！当前促销:{}算价结果中的sku:{}的分摊计算'.format(pro['proId'], sku)})
                        else:
                            exc_value = '当前商品分摊校验不通过！促销id为：{}({})，商品sku为：{}，期望分摊结果：{}，实际分摊结果：{}'.format(
                                pro['proId'], pro['proName'], sku, share_exp, share['shareDiscount'])
                            verification_res[sku] = [False, exc_value]
                            shares_skus_res[sku] = [share_exp, share['shareDiscount']]
                            # log_all.append({'error': '错误！！！当前促销:{}算价结果中的sku:{}的分摊计算'.format(pro['proId'], share['sku'])})
                        l = 1
                if l == 1:
                    pass
                else:
                    exc_value = '促销：{}({})，sku:{}未进行分摊校验！！！'.format(pro['proId'], pro['proName'], sku)
                    verification_res[sku] = [False, exc_value]
            # 这里的差额是1还是多少，应该可以用计算来获得。每个商品的分摊都用四舍五入，然后与实际的优惠金额做减法，就可以得到差额。
            res = 0
            for sku in sku_totalPrice:
                if pro['skuDiscount'] is not None:  # 说明是赠品或者换购
                    sku_type = sku.split('__')[1]
                    if sku_type != 'MAIN_SKU' and int(sku.split('__')[2]) == pro['proId']:
                        if totalPrice != 0:
                            share_exp = sku_totalPrice[sku] * (discount / totalPrice)  # 还是要经过计算，避免后续出现多个赠品/换购品时计算不正确
                            share_exp = round(share_exp)
                            if share_exp < 0:
                                share_exp = 0
                            res += share_exp
                        else:
                            if pro['skuDiscount'] == 0:
                                # 整单促销，赠品为0，还是可以正常享受促销。其他促销不行
                                pass
                    else:
                        share_exp = 0
                else:  # 除赠品和换购之外的其他促销分摊计算
                    if totalPrice != 0:
                        share_exp = sku_totalPrice[sku] * (discount / totalPrice)
                        share_exp = round(share_exp)
                        if share_exp < 0:
                            share_exp = 0
                        res += share_exp
            deviation = abs(res - discount)
            if deviation == 0:
                deviation = 1
            # 为了避免计算顺序不同。如果分摊结果中存在两个sku错误，一个多了偏离值一个少了偏离值，那么认为分摊是正确的
            flag_value = 0
            for sku, share in shares_skus_res.items():
                if share[0] is not True:
                    log_all.append({'info': '偏离值deviation:{}。'.format(deviation)})
                    err_value = share[0] - share[1]
                    if err_value in [deviation, -deviation] and flag_value == 0:
                        log_all.append({
                            'info': '当前促销:{}，sku:{}的接口返回分摊为：{}，与期望误差{}。说明计算分摊顺序不一致。'.format(
                                pro['proId'],
                                sku, share[1],
                                err_value)})
                        flag_value = err_value
                        continue
                    elif err_value in [deviation, -deviation] and flag_value != 0:
                        log_all.append({
                            'info': '当前促销:{}，sku:{}的接口返回分摊为：{}，与期望误差{}。说明计算分摊顺序不一致。'.format(
                                pro['proId'],
                                sku, share[1],
                                err_value)})
                        if err_value + flag_value == 0:
                            for key, value in verification_res.items():
                                if key in shares_skus_res.keys():
                                    verification_res[key] = [True]
                    else:
                        exc_value = '当前商品分摊校验不通过！促销id为：{}({})，商品sku为：{}，期望分摊结果：{}，实际分摊结果：{}'.format(
                            pro['proId'], pro['proName'], sku, share[0], share[1])
                        verification_res[sku] = [False, exc_value]
                        log_all.append(
                            {'error': '错误！！！当前促销:{}算价结果中的sku:{}的分摊计算'.format(pro['proId'],
                                                                                              int(sku.split('__')[0]))})

            verification_res_values = []
            for value in verification_res.values():
                verification_res_values.append(value[0])
            if False in verification_res_values:
                err = []
                for key, value in verification_res.items():
                    if False in value:
                        err.append(key)
                log_all.append({'error': '失败！！！促销：{}，存在校验失败字段，具体字段列表：{}'.format(pro['proId'], err)})
            else:
                log_all.append({'info': '成功！促销：{}，所有字段值校验均正确：{}'.format(pro['proId'],
                                                                                      list(verification_res.keys()))})
            verification_res_all[pro['proId']] = verification_res
        if len(exps) == 0:
            log_all.append({'info': '期望命中促销为空，不存在分摊数据。'})
        return verification_res_all, log_all

    def __result_check_proId_skus(self, res_separate, exps=[]):
        """
        校验单个促销，期望被哪些商品分摊

        :param res_separate: 分解后的算价结果。格式：{'pros': pros_sort, 'shares': skus_share_info}
        :param exps:期望命中的促销列表，格式：exp = [{'proId_exp': 2021030500000881, 'proSlogan': 'XX', 'showSlogan': 'XX'}]
        :return:
        """
        verification_res_all = {}
        log_all = [{'info': '\n'}, {'info': '================开始校验促销实际被哪些商品分摊================'}]
        for pro_exp in exps:
            if pro_exp.get('skus_exp'):
                verification_res = {}
                proId_exp = pro_exp['proId_exp']
                skus_exp = pro_exp['skus_exp']
                if isinstance(skus_exp, list):
                    pass
                elif isinstance(skus_exp, dict):
                    skus_exp = list(skus_exp.keys())
                else:
                    raise Exception('促销：{}，skus_exp格式不正确，期望为列表或者字典！！！'.format(proId_exp))
                log_all.append({'info': '当前校验促销：{}'.format(proId_exp)})
                shares = res_separate['shares']
                skus = []
                for share in shares:
                    if int(share['proId']) == int(proId_exp):
                        skus.append(share['sku'])
                proName = None
                for pro in res_separate['pros']:
                    if pro['proId'] == proId_exp:
                        proName = pro['proName']

                skus.sort()
                skus_exp.sort()

                if skus == skus_exp:
                    verification_res['期望被分摊的商品'] = [True]
                    log_all.append({
                        'info': '成功！促销：{}，促销期望被分摊的商品与实际相同。实际分摊该促销的sku列表为：{}'.format(
                            proId_exp, skus)})
                else:
                    exc_value = '促销：{}({}),期望被分摊的商品与实际不符，期望为：{}，实际为：{}'.format(proId_exp, proName,
                                                                                                    skus_exp, skus)
                    verification_res['期望被分摊的商品'] = [False, exc_value]
                    log_all.append(
                        {'error': '失败！！！促销：{}，促销期望被分摊的商品与实际不一致。期望为：{}，实际为：{}'.format(
                            proId_exp, skus_exp, skus)})
                verification_res_all[proId_exp] = verification_res
            else:
                log_all.append(
                    {'info': '促销：{}，没有传入"skus_exp"，不校验促销实际被哪些商品分摊'.format(pro_exp['proId_exp'])})
        if len(exps) == 0:
            log_all.append({'info': '期望不命中任何促销，不校验促销实际被哪些商品分摊'})
        return verification_res_all, log_all

    def __result_check_shares_by_exp(self, res_separate, exps=[]):
        """
        期望结果中带有shares_exp的，直接用这个方法计算分摊与期望结果一致

        :param res_separate:
        :param exps:
        :return:
        """
        verification_res_all = {}
        log_all = [{'info': '\n'},
                   {'info': '================开始校验促销实际被哪些商品分摊，以及对应的分摊金额================'}]
        for pro_exp in exps:
            if pro_exp.get('shares_exp'):
                verification_res = {}
                proId_exp = pro_exp['proId_exp']
                shares_exp = pro_exp['shares_exp']
                if isinstance(shares_exp, list):
                    pass
                else:
                    raise Exception('促销：{}，skus_exp格式不正确，期望为列表或者字典！！！'.format(proId_exp))
                log_all.append({'info': '当前校验促销：{}'.format(proId_exp)})
                shares = res_separate['shares']
                shares_res = []
                for share in shares:
                    if int(share['proId']) == int(proId_exp):
                        shares_res.append(str(share['sku']) + ': ' + str(share['shareDiscount']))
                proName = None
                for pro in res_separate['pros']:
                    if pro['proId'] == proId_exp:
                        proName = pro['proName']

                shares_res.sort()
                shares_exp.sort()

                # 添加校验，如果分摊存在负数，直接返回失败
                flag = False
                for s in shares_res:
                    if int(s.split(': ')[1]) < 0:
                        flag = True
                        break
                if flag is True:
                    exc_value = '促销：{}({}),实际分摊结果中存在负数，校验不通过，期望为：{}，实际为：{}'.format(proId_exp,
                                                                                                           proName,
                                                                                                           shares_exp,
                                                                                                           shares_res)
                    verification_res['期望的分摊结果'] = [False, exc_value]
                    log_all.append({
                        'error': '失败！！！促销：{},实际分摊结果中存在负数，校验不通过，期望为：{}，实际为：{}'.format(
                            proId_exp, shares_exp,
                            shares_res)})
                    verification_res_all[proId_exp] = verification_res
                    continue

                # 如果整体匹配直接相等，就可以确认分摊正确
                if shares_res == shares_exp:
                    verification_res['期望的分摊结果'] = [True]
                    log_all.append({'info': '成功！促销：{}，期望的分摊结果与实际相同。实际分摊结果为：{}'.format(proId_exp,
                                                                                                             shares_res)})
                else:
                    # 如果整体匹配不通过，也有一种情况可以被认为是正确的
                    # 判断为正确的两个点：1.分摊的项数相同；2.分摊总额相等；3.其中两个sku的分摊值，一个多1一个少1，其他sku的分摊值一致
                    if len(shares_res) == len(shares_exp):
                        # 判断分摊总额相等
                        total_res, total_exp = 0, 0
                        for r in shares_res:
                            total_res += int(r.split(': ')[1])
                        for e in shares_exp:
                            total_exp += int(e.split(': ')[1])
                        # 如果总分摊金额相等，继续判断
                        if total_res == total_exp:
                            # 偏离值，可以估算为：分摊的商品总个数除以二
                            deviation = 1
                            for res_s in res_separate.get('shares'):
                                if res_s.get('proId') == proId_exp:
                                    deviation += res_s.get('num')
                            deviation = int(deviation / 2)
                            # 判断其中两个sku的分摊值，一个多1一个少1，其他sku的分摊值一致
                            log_all_d = []
                            for d in range(1, deviation):
                                flag_value = 0
                                verification_res['期望的分摊结果'] = [True]
                                log_all_d = [{'info': '当前偏离值为：{}'.format(d)}]
                                for res, exp in zip(shares_res, shares_exp):
                                    sku = res.split(': ')[0]
                                    err_value = int(res.split(': ')[1]) - int(exp.split(': ')[1])
                                    if err_value in [d, -d] and flag_value == 0:
                                        flag_value = err_value
                                        log_all_d.append({
                                            'info': '当前促销:{}，sku:{}的分摊与期望误差{}。说明计算分摊顺序不一致。'.format(
                                                proId_exp, sku, err_value)})
                                    elif err_value in [d, -d] and flag_value != 0:
                                        if err_value + flag_value == 0:
                                            log_all_d.append({
                                                'info': '当前促销:{}，sku:{}的分摊与期望误差{}。说明计算分摊顺序不一致。'.format(
                                                    proId_exp, sku, err_value)})
                                    elif err_value == 0:
                                        pass
                                    else:
                                        exc_value = '促销：{}({}),期望的分摊结果与实际不符，期望为：{}，实际为：{}'.format(
                                            proId_exp, proName,
                                            shares_exp,
                                            shares_res)
                                        verification_res['期望的分摊结果'] = [False, exc_value]
                                        log_all_d.append({
                                            'error': '失败！！！促销：{},期望的分摊结果与实际不符，期望为：{}，实际为：{}'.format(
                                                proId_exp, shares_exp, shares_res)})
                                if verification_res['期望的分摊结果'] == [True]:
                                    break
                            log_all.extend(log_all_d)
                        else:
                            exc_value = '促销：{}({}),期望的分摊结果与实际不符，期望为：{}，实际为：{}'.format(proId_exp,
                                                                                                          proName,
                                                                                                          shares_exp,
                                                                                                          shares_res)
                            verification_res['期望的分摊结果'] = [False, exc_value]
                            log_all.append({
                                'error': '失败！！！促销：{},期望的分摊结果与实际不符，期望为：{}，实际为：{}'.format(
                                    proId_exp,
                                    shares_exp,
                                    shares_res)})
                    else:
                        exc_value = '促销：{}({}),期望的分摊结果与实际不符，期望为：{}，实际为：{}'.format(proId_exp,
                                                                                                      proName,
                                                                                                      shares_exp,
                                                                                                      shares_res)
                        verification_res['期望的分摊结果'] = [False, exc_value]
                        log_all.append({'error': '失败！！！促销：{},期望的分摊结果与实际不符，期望为：{}，实际为：{}'.format(
                            proId_exp, shares_exp,
                            shares_res)})
                verification_res_all[proId_exp] = verification_res
        if len(exps) == 0:
            log_all.append({'info': '期望不命中任何促销，不校验促销实际的分摊结果'})
        return verification_res_all, log_all

    def __result_check_skus_info(self, res_separate):
        """
        校验singleSkuItem中的各个值是否正确

        :param res_separate:
        :return:
        """
        pros = res_separate['pros']
        # 处理为促销id对应促销类型
        pros_type = {}
        for pro in pros:
            if pro['proId'] in pros_type.keys():
                continue
            else:
                pros_type[pro['proId']] = pro['proType']

        skus_info = res_separate['skus_info']
        # print("-----------------------")
        # print(skus_info)
        verification_res_all = {}
        log_all = [{'info': '\n'}, {'info': '================开始校验singleSkuItem中的各个值是否正确================'}]
        # 校验totalSettlePrice、totalOrigPrice
        realityRewardQty = 0
        dict_realityRewardQty = {}
        dict_itemNums = {}
        for sku_info in skus_info:
            if sku_info.get('skuType') == 'MAIN_SKU':
                packNum = sku_info.get('packNum')
                dict_itemNums.setdefault(sku_info.get("skuId"), packNum)
            else:
                rewardQty = sku_info.get('rewardQty')
                realityRewardQty += rewardQty
                dict_realityRewardQty[sku_info.get("skuId")] = realityRewardQty
                if sku_info.get("skuId") in dict_itemNums.keys():
                    dict_itemNums[sku_info.get("skuId")] = rewardQty + dict_itemNums[sku_info.get("skuId")]
                else:
                    dict_itemNums.setdefault(sku_info.get("skuId"), 0)
                    dict_itemNums[sku_info.get("skuId")] += rewardQty
        for sku_info in skus_info:
            verification_res = {}
            sku_ind = str(sku_info.get('skuId')) + '_' + str(skus_info.index(sku_info))
            totalSettlePrice = sku_info.get('totalSettlePrice')
            # totalOrigPrice = sku_info.get('totalOrigPrice')
            skuProShareInfoList = sku_info.get('skuProShareInfoList', None)
            # 计算原价
            packNum = 0
            if sku_info.get('skuType') == 'MAIN_SKU':
                packNum = sku_info.get('packNum')
            else:
                packNum = sku_info.get('rewardQty')
            packPrice = 0
            for ware in self.ware_data:
                if ware['skuId'] == sku_info.get('skuId'):
                    # packPrice = ware['packPrice']  #相同sku多个商品行时取值会出错
                    if sku_info.get('skuType') == 'MAIN_SKU':
                        packPrice = sku_info.get("origPrice")
                        if packPrice not in jsonpath.jsonpath(self.ware_data, '$..%s' % 'packPrice'):
                            exc_value = '商品：{}({}),返回的origPrice不正确，不为入参中存在的数据，导致本次计算出来的totalSettlePrice_exp不具备参考性，实际为：{}'.format(
                                sku_ind, sku_info.get('skuName'), packPrice)
                            verification_res['packPrice'] = [False, exc_value]
                            log_all.append({'error': '失败！！！{}'.format(exc_value)})
                        break
                    else:
                        if dict_realityRewardQty[sku_info.get("skuId")] < dict_itemNums[sku_info.get("skuId")]:
                            print("我不相等了，取原价")
                            packPrice = sku_info.get("origPrice")
                        else:
                            print("我相等了，要取平均价")
                            packPrice = sku_info.get("averageProPrice")

            totalOrigPrice = packPrice * packNum
            shareDiscounts = 0
            # unit_shareDiscounts = 0
            if skuProShareInfoList is not None:
                for skuProShareInfo in skuProShareInfoList:
                    if sku_info.get('skuType') == 'TRADE_SKU' and sku_info.get('proId', "") == skuProShareInfo.get(
                            "proId", ""):
                        shareDiscount = skuProShareInfo.get('shareDiscount', 0)
                        shareDiscounts += shareDiscount
                    elif sku_info.get('skuType') == 'MAIN_SKU':
                        shareDiscount = skuProShareInfo.get('shareDiscount', 0)
                        shareDiscounts += shareDiscount
                    elif sku_info.get(
                            'skuType') == 'GIFT_SKU':  # and sku_info.get('proId', "") == skuProShareInfo.get("proId", "")
                        shareDiscount = skuProShareInfo.get('shareDiscount', 0)
                        shareDiscounts += shareDiscount
                    # else:
                    #     print("没有匹配到商品类型")
                    #     shareDiscount = skuProShareInfo.get('shareDiscount', 0)
                    #     shareDiscounts += shareDiscount
                    # pro = skuProShareInfo.get('proId')
                    # if pros_type[pro] == 'UNIT':
                    #     unit_shareDiscounts += shareDiscount
            totalSettlePrice_exp = totalOrigPrice - shareDiscounts
            if totalSettlePrice == totalSettlePrice_exp:
                verification_res['totalSettlePrice'] = [True]
                log_all.append({'info': '成功！商品：{}({})，返回的totalSettlePrice正确，值为：{}'.format(sku_ind,
                                                                                                     sku_info.get(
                                                                                                         'skuName'),
                                                                                                     totalSettlePrice)})
            else:
                exc_value = '商品：{}({}),返回的totalSettlePrice不正确，期望为：{}，实际为：{}'.format(sku_ind, sku_info.get(
                    'skuName'), totalSettlePrice_exp, totalSettlePrice)
                verification_res['totalSettlePrice'] = [False, exc_value]
                log_all.append({'error': '失败！！！商品：{}({}),返回的totalSettlePrice不正确，期望为：{}，实际为：{}'.format(
                    sku_ind, sku_info.get('skuName'), totalSettlePrice_exp, totalSettlePrice)})
            # if sku_info.get('skuType') == 'MAIN_SKU':
            #     if totalOrigPrice == totalOrigPrice_exp:
            #         verification_res['totalOrigPrice'] = [True]
            #         log_all.append({'info': '成功！商品：{}({})，返回的totalProPrice正确，值为：{}'.
            #                        format(sku_ind, sku_info.get('skuName'), totalOrigPrice)})
            #     else:
            #         exc_value = '商品：{}({}),返回的totalProPrice不正确，期望为：{}，实际为：{}'.\
            #             format(sku_ind, sku_info.get('skuName'), totalOrigPrice_exp, totalOrigPrice)
            #         verification_res['totalOrigPrice'] = [False, exc_value]
            #         log_all.append({'error': '失败！！！商品：{}({}),返回的totalProPrice不正确，期望为：{}，实际为：{}'.
            #                        format(sku_ind, sku_info.get('skuName'), totalOrigPrice_exp, totalOrigPrice)})

            verification_res_all[sku_ind] = verification_res
        return verification_res_all, log_all

    # def __result_check_paperCouponResults(self, ticket, res_original):
    #     """
    #     校验纸质券码的消耗次数
    #     :param res_original:
    #     :return:
    #     """
    #     verification_res_all = {}
    #     log_all = [{'info': '\n'}, {'info': '================开始校验校验纸质券码的消耗次数================'}]
    #     paper_coupon_results = res_original.get('paperCouponResults')
    #     if paper_coupon_results is not None:
    #         log_all.append({'info': '接口返回的纸质券码使用情况为：{}'.format(paper_coupon_results)})
    #
    #     paper_coupon_results_exp = self.data.get('paper_coupon_results_exp')
    #     if paper_coupon_results_exp is None:
    #         log_all.append({'info': '没有传入paper_coupon_results_exp，不校验纸质券码的消耗情况'})
    #         return verification_res_all, log_all
    #     # 获取paper_coupon_results_exp中的值
    #     for res_exp in paper_coupon_results_exp:
    #         verification_res = {}
    #         couponCode_exp = res_exp['couponCode']  # 获取用例中couponCode
    #         for res in paper_coupon_results:
    #             couponCode = res['couponCode']  # 获取接口返回的couponCode
    #             if couponCode == res_exp['couponCode']:
    #                 # 校验每个促销相关
    #                 proUseCoupon_useCount_exp_count = 0
    #                 for proUseCoupon_proid_exp, proUseCoupon_useCount_exp in res_exp['proUseCoupons'].items():
    #                     address_proengine = self.env_hosts['partnerPro']
    #                     proInfo = ProInfo(address_proengine)
    #                     for proUseCoupon in res['proUseCoupons']:
    #                         if proUseCoupon.get('proId') == proUseCoupon_proid_exp:
    #                             # 校验proUsedCount
    #                             if proUseCoupon['proUsedCount'] == proUseCoupon_useCount_exp:
    #                                 verification_res['{}_proUsedCount'.format(proUseCoupon_proid_exp)] = [True]
    #                                 log_all.append(
    #                                     {'info': '成功！资格码：{}，促销id：{}，消耗次数proUsedCount校验正确。消耗次数为：{}'.
    #                                     format(couponCode, proUseCoupon_proid_exp,
    #                                            proUseCoupon_useCount_exp)})
    #                                 if int(proUseCoupon['proUsedCount']) > proUseCoupon_useCount_exp_count:
    #                                     proUseCoupon_useCount_exp_count = int(proUseCoupon['proUsedCount'])
    #                             else:
    #                                 exc_value = '资格码：{}，促销id：{}，消耗次数proUsedCount校验不通过，期望为：{}，实际为：{}'. \
    #                                     format(couponCode, proUseCoupon_proid_exp, proUseCoupon_useCount_exp,
    #                                            proUseCoupon['proUsedCount'])
    #                                 verification_res['{}_proUsedCount'.format(proUseCoupon_proid_exp)] = [False,
    #                                                                                                       exc_value]
    #                                 log_all.append(
    #                                     {'error': '失败！！！促销id：{}，消耗次数proUsedCount校验不通过，期望为：{}，实际为：{}'.
    #                                     format(couponCode, proUseCoupon_proid_exp, proUseCoupon_useCount_exp,
    #                                            proUseCoupon['proUsedCount'])})
    #                             # 校验proSlogan
    #                             pro_info = proInfo.pro_view(ticket, proUseCoupon_proid_exp)
    #                             proSloganMap = pro_info.get('showInfo', {}).get('showInfoPos', {}).get('proSloganMap',
    #                                                                                                    {})
    #                             if self.offline_flag is False:  # 离线只会返回繁体中文促销语
    #                                 proSlogan_exp = proSloganMap.get(self.language)
    #                             else:
    #                                 proSlogan_exp = proSloganMap.get('zh_HK')
    #                             if proUseCoupon.get('proSlogan') == proSlogan_exp:
    #                                 verification_res['{}_proSlogan'.format(proUseCoupon_proid_exp)] = [True]
    #                                 log_all.append({'info': '成功！资格码：{}，促销id：{}，促销语proSlogan校验正确：{}'.
    #                                                format(couponCode, proUseCoupon_proid_exp, proSlogan_exp)})
    #                             else:
    #                                 exc_value = '资格码：{}，促销id：{}，促销语proSlogan校验不通过，期望为：{}，实际为：{}'. \
    #                                     format(couponCode, proUseCoupon_proid_exp, proSlogan_exp,
    #                                            proUseCoupon.get('proSlogan'))
    #                                 verification_res['{}_proSlogan'.format(proUseCoupon_proid_exp)] = [False, exc_value]
    #                                 log_all.append(
    #                                     {'error': '失败！！！促销id：{}，促销语proSlogan校验不通过，期望为：{}，实际为：{}'.
    #                                     format(couponCode, proUseCoupon_proid_exp, proSlogan_exp,
    #                                            proUseCoupon.get('proSlogan'))})
    #                 # 校验usedCount
    #                 usedCount_exp = res_exp.get('usedCount')
    #                 if usedCount_exp is None:
    #                     usedCount_exp = proUseCoupon_useCount_exp_count
    #                 if res['usedCount'] == usedCount_exp:
    #                     verification_res['usedCount'] = [True]
    #                     log_all.append(
    #                         {'info': '成功！资格码：{}，总消耗次数usedCount校验正确。消耗次数为：{}'.format(couponCode, res[
    #                             'usedCount'])})
    #                 else:
    #                     exc_value = '资格码：{},总消耗次数usedCount校验不通过，期望为：{}，实际为：{}'.format(couponCode,
    #                                                                                                      usedCount_exp,
    #                                                                                                      res[
    #                                                                                                          'usedCount'])
    #                     verification_res['usedCount'] = [False, exc_value]
    #                     log_all.append({'error': '失败！！！资格码：{},总消耗次数usedCount校验不通过，期望为：{}，实际为：{}'.
    #                                    format(res['couponCode'], usedCount_exp, res['usedCount'])})
    #                 # 资格码对应的促销数相同
    #                 proIds = []
    #                 for proUseCoupon in res['proUseCoupons']:
    #                     proIds.append(proUseCoupon['proId'])
    #                 if sorted(list(res_exp['proUseCoupons'].keys())) == sorted(proIds):
    #                     verification_res['proCount'] = [True]
    #                     log_all.append({'info': '成功！资格码：{}，命中的促销校验正确：{}'.format(couponCode, proIds)})
    #                 else:
    #                     exc_value = '资格码：{},命中的促销校验不通过，期望为：{}，实际为：{}'. \
    #                         format(couponCode, list(res_exp['proUseCoupons'].keys()), proIds)
    #                     verification_res['proCount'] = [False, exc_value]
    #                     log_all.append({'error': '失败！！！资格码：{},命中的促销校验不通过，期望为：{}，实际为：{}'.
    #                                    format(couponCode, list(res_exp['proUseCoupons'].keys()), proIds)})
    #             # 校验totalCount
    #             for barCode in self.others_data['barCodeList']:
    #                 if couponCode == int(str(barCode).split('_')[0]):
    #                     if len(str(barCode).split('_')) == 1:
    #                         totalCount_exp = None
    #                         newCoupon_exp = False
    #                     elif str(barCode).split('_')[1] == '0':
    #                         totalCount_exp = None
    #                         newCoupon_exp = True
    #                     else:
    #                         totalCount_exp = int(str(barCode).split('_')[1])
    #                         newCoupon_exp = True
    #                     if res.get('totalCount') == totalCount_exp:
    #                         verification_res['totalCount'] = [True]
    #                         log_all.append(
    #                             {'info': '成功！资格码：{}，总次数totalCount校验正确。值为：{}'.format(couponCode, res.get(
    #                                 'totalCount'))})
    #                     else:
    #                         exc_value = '资格码：{},总次数totalCount校验不通过，期望为：{}，实际为：{}'.format(couponCode,
    #                                                                                                       totalCount_exp,
    #                                                                                                       res.get(
    #                                                                                                           'totalCount'))
    #                         verification_res['usedCount'] = [False, exc_value]
    #                         log_all.append({'error': '失败！！！资格码：{},总次数totalCount校验不通过，期望为：{}，实际为：{}'.
    #                                        format(res['couponCode'], totalCount_exp, res.get('totalCount'))})
    #             # 校验newCoupon
    #             for barCode in self.others_data['barCodeList']:
    #                 if couponCode == int(str(barCode).split('_')[0]):
    #                     if res.get('newCoupon') == newCoupon_exp:
    #                         verification_res['newCoupon'] = [True]
    #                         log_all.append(
    #                             {'info': '成功！资格码：{}，是否为UMO码校验正确。值为：{}'.format(couponCode,
    #                                                                                          res.get('newCoupon'))})
    #                     else:
    #                         exc_value = '资格码：{},是否为UMO码校验不通过，期望为：{}，实际为：{}'.format(couponCode,
    #                                                                                                  newCoupon_exp,
    #                                                                                                  res.get(
    #                                                                                                      'newCoupon'))
    #                         verification_res['newCoupon'] = [False, exc_value]
    #                         log_all.append({'error': '失败！！！资格码：{},是否为UMO码校验不通过，期望为：{}，实际为：{}'.
    #                                        format(res['couponCode'], newCoupon_exp, res.get('newCoupon'))})
    #         verification_res_all[couponCode_exp] = verification_res
    #         # 校验资格码相同
    #         coupons_exp = []
    #         for coupon_exp in paper_coupon_results_exp:
    #             coupons_exp.append(str(coupon_exp['couponCode']))
    #         coupons = []
    #         for coupon in paper_coupon_results:
    #             coupons.append(str(coupon['couponCode']))
    #         verification_res = {}
    #         if sorted(coupons_exp) == sorted(coupons):
    #             verification_res['资格码'] = [True]
    #             log_all.append({'info': '成功！总校验资格码正确：{}'.format(sorted(coupons))})
    #         else:
    #             exc_value = '总校验资格码不正确，期望为：{}，实际为：{}'.format(sorted(coupons_exp), sorted(coupons))
    #             verification_res['资格码'] = [False, exc_value]
    #             log_all.append({'error': '失败！！！总校验资格码不正确，期望为：{}，实际为：{}'.
    #                            format(sorted(coupons_exp), sorted(coupons))})
    #         verification_res_all['资格码'] = verification_res
    #     return verification_res_all, log_all

    # def __result_check_proSkuEnjoyInfos(self, ticket, res_original):
    #     """
    #     校验促销返回返利件数
    #     :param res_original:
    #     :return:
    #     """
    #     verification_res_all = {}
    #     log_all = [{'info': '\n'}, {'info': '================开始校校验促销返回返利件数================'}]
    #     proSkuEnjoyInfos = res_original.get('proSkuEnjoyInfos')
    #     if proSkuEnjoyInfos is not None:
    #         log_all.append({'info': '接口返回的促销返回返利件数使用情况为：{}'.format(proSkuEnjoyInfos)})
    #
    #     pro_sku_enjoyinfos_exp = self.data.get('pro_sku_enjoyinfos_exp')
    #     if pro_sku_enjoyinfos_exp is None:
    #         log_all.append({'info': '没有传入pro_sku_enjoyinfos_exp，不校验促销返回返利件'})
    #         return verification_res_all, log_all
    #     # 获取pro_sku_enjoyinfos_exp中的值
    #     verification_res = {}
    #     proId_exps = []
    #     for proId_exp in pro_sku_enjoyinfos_exp:
    #         proId_exps.append(str(proId_exp['proId']))
    #     proIds = []
    #     for proId in proSkuEnjoyInfos:
    #         proIds.append(str(proId['proId']))
    #     if sorted(proId_exps) == sorted(proIds):
    #         verification_res['返利件数'] = [True]
    #         log_all.append({'info': '成功！总校验返利促销ID正确：{}'.format(sorted(proIds))})
    #     else:
    #         exc_value = '总校验返利促销ID不正确，期望为：{}，实际为：{}'.format(sorted(proId_exps), sorted(proIds))
    #         verification_res['返利件数'] = [False, exc_value]
    #         log_all.append({'error': '失败！！！总校验返利促销ID不正确，期望为：{}，实际为：{}'.
    #                        format(sorted(proId_exps), sorted(proIds))})
    #         verification_res_all['所有促销ID'] = verification_res
    #         return verification_res_all, log_all
    #     for res_exp in pro_sku_enjoyinfos_exp:
    #         for res in proSkuEnjoyInfos:
    #             proId_exp = res_exp['proId']
    #             proId = res['proId']
    #             if proId == proId_exp:
    #                 # 校验每个促销相关商品
    #                 sku_exps = [str(i) for i in res_exp['skuCount'].keys()]
    #                 skus = res['sku2Count'].keys()
    #                 if sorted(sku_exps) == sorted(skus):
    #                     for enjoyinfos_skuid_exp, enjoyinfos_skuNum_exp in res_exp['skuCount'].items():
    #                         res_sku = res['sku2Count']
    #                         enjoyinfos_skuNum = res_sku[str(enjoyinfos_skuid_exp)]
    #                         if enjoyinfos_skuNum == enjoyinfos_skuNum_exp:
    #                             exc_value = '返回返利商品{}数量正确，期望为：{}，实际为：{}'.format(enjoyinfos_skuid_exp,
    #                                                                                             enjoyinfos_skuNum_exp,
    #                                                                                             enjoyinfos_skuNum)
    #                             log_all.append({'info': '返回返利商品{}数量正确，期望为：{}，实际为：{}'.
    #                                            format(enjoyinfos_skuid_exp, enjoyinfos_skuNum_exp, enjoyinfos_skuNum)})
    #                             verification_res[str(enjoyinfos_skuid_exp)] = [True, exc_value]
    #                         else:
    #                             exc_value = '返回返利商品{}数量不正确，期望为：{}，实际为：{}'.format(enjoyinfos_skuid_exp,
    #                                                                                               enjoyinfos_skuNum_exp,
    #                                                                                               enjoyinfos_skuNum)
    #                             log_all.append({'info': '返回返利商品{}数量不正确，期望为：{}，实际为：{}'.
    #                                            format(enjoyinfos_skuid_exp, enjoyinfos_skuNum_exp, enjoyinfos_skuNum)})
    #                             verification_res[str(enjoyinfos_skuid_exp)] = [False, exc_value]
    #                 else:
    #                     exc_value = '总校验返利商品ID不正确，期望为：{}，实际为：{}'.format(pro_sku_enjoyinfos_exp,
    #                                                                                     proSkuEnjoyInfos)
    #                     verification_res['sku对比'] = [False, exc_value]
    #                     log_all.append({'error': '失败！！！总校验返利商品ID不正确，期望为：{}，实际为：{}'.
    #                                    format(sorted(sku_exps), sorted(skus))})
    #         verification_res_all['返利件数'] = verification_res
    #     return verification_res_all, log_all

    # def __result_check_cashierAlerts(self, ticket, res_original):
    #     """
    #     校验收银员赠品提示信息
    #     :param res_original:
    #     :return:
    #     """
    #     verification_res_all = {}
    #     log_all = [{'info': '\n'}, {'info': '================开始校验校验：收银台赠品提示信息================'}]
    #
    #     cashierAlerts_exp = self.data.get('cashierAlerts_exp')
    #     if cashierAlerts_exp is None:
    #         log_all.append({'info': '没有传入cashierAlerts_exp，不校验收银台赠品提示信息'})
    #         return verification_res_all, log_all
    #
    #     cashierAlerts = res_original.get('cashierAlerts')
    #     if cashierAlerts is not None:
    #         log_all.append({'info': '接口返回的收银台赠品提示信息为：{}'.format(cashierAlerts)})
    #     else:
    #         if self.others_data.get('showCashierAlert', False) is False:
    #             verification_res = {'cashierAlerts': [True]}
    #             log_all.append({'info': 'cashierAlerts没有命中任何活动时，不返回该字段。'})
    #         else:
    #             if cashierAlerts_exp:
    #                 exc_value = '期望返回cashierAlerts为：{}，实际未返回该字段'.format(cashierAlerts_exp)
    #                 log_all.append({'error': '失败！！！{}'.format(exc_value)})
    #                 verification_res = {'cashierAlerts': [False, exc_value]}
    #             else:
    #                 verification_res = {'cashierAlerts': [True]}
    #                 log_all.append({'info': 'cashierAlerts没有命中任何活动时，不返回该字段。'})
    #         verification_res_all['cashierAlerts'] = verification_res
    #         return verification_res_all, log_all
    #
    #     # 获取cashierAlerts_exp中的值
    #     ids_exp = []
    #     for res_exp in cashierAlerts_exp:
    #         verification_res = {}
    #         check_infos = {}
    #         proId_exp = res_exp['proId_exp']
    #         ids_exp.append(proId_exp)
    #         for res in cashierAlerts:
    #             if res['proId'] == proId_exp:
    #                 # 校验triggerTimes
    #                 if res_exp.get('triggerTimes') is not None:
    #                     triggerTimes_exp = res_exp.get('triggerTimes')
    #                     check_infos['触发次数triggerTimes'] = [triggerTimes_exp, res['triggerTimes']]
    #
    #                 # 查询活动详情
    #                 address_proengine = self.env_hosts['partnerPro']
    #                 proInfo = ProInfo(address_proengine)
    #                 pro_info = proInfo.pro_view(ticket, proId_exp)
    #                 # 校验qualifications。没有黑名单商品的话，可以直接取算价结果，如果有，则必须指定
    #                 if pro_info['baseInfo']['proType'] == '收银台赠品活动':
    #                     pro_triggers = pro_info['cashierRule']['triggers']
    #                     for trigger in pro_triggers:
    #                         triggerType = trigger.get('triggerType')
    #                         if triggerType == 1:  # 门槛件数
    #                             if res_exp.get('qualifications_Q_exp') is not None:
    #                                 qualifications_Q_exp = res_exp.get('qualifications_Q_exp')  # 如果有期望值，那么置为期望值
    #                             else:
    #                                 qualifications_Q_exp = 0
    #                                 for sku in self.ware_data:
    #                                     qualifications_Q_exp += sku['packNum']
    #                             qualifications_Q = '没有返回该字段'
    #                             for qualification in res['qualifications']:
    #                                 if qualification['triggerType'] == 1:
    #                                     qualifications_Q = qualification['value']
    #                             check_infos['触发门槛件数'] = [qualifications_Q_exp, qualifications_Q]
    #                         elif triggerType == 2:  # 门槛金额
    #                             if res_exp.get('qualifications_A_exp') is not None:
    #                                 qualifications_A_exp = res_exp.get('qualifications_A_exp')  # 如果有期望值，那么置为期望值
    #                             else:
    #                                 qualifications_A_exp = res_original.get('orderTotalSettlePrice')
    #                             qualifications_A = '没有返回该字段'
    #                             for qualification in res['qualifications']:
    #                                 if qualification['triggerType'] == 2:
    #                                     qualifications_A = qualification['value']
    #                             check_infos['触发门槛金额'] = [qualifications_A_exp, qualifications_A]
    #                 else:
    #                     triggerType = pro_info['rule']['triggerType']
    #                     if triggerType == 1:  # 门槛件数
    #                         if res_exp.get('qualifications_Q_exp') is not None:
    #                             qualifications_Q_exp = res_exp.get('qualifications_Q_exp')  # 如果有期望值，那么置为期望值
    #                         else:
    #                             qualifications_Q_exp = 0
    #                             for sku in self.ware_data:
    #                                 qualifications_Q_exp += sku['packNum']
    #                         qualifications_Q = '没有返回该字段'
    #                         for qualification in res['qualifications']:
    #                             if qualification['triggerType'] == 1:
    #                                 qualifications_Q = qualification['value']
    #                         check_infos['触发门槛件数'] = [qualifications_Q_exp, qualifications_Q]
    #                     elif triggerType == 2:  # 门槛金额
    #                         if res_exp.get('qualifications_A_exp') is not None:
    #                             qualifications_A_exp = res_exp.get('qualifications_A_exp')  # 如果有期望值，那么置为期望值
    #                         else:
    #                             qualifications_A_exp = res_original.get('orderTotalSettlePrice')
    #                         qualifications_A = '没有返回该字段'
    #                         for qualification in res['qualifications']:
    #                             if qualification['triggerType'] == 2:
    #                                 qualifications_A = qualification['value']
    #                         check_infos['触发门槛金额'] = [qualifications_A_exp, qualifications_A]
    #
    #                 # 校验cashierGiftSkuInfos。直接从促销详情中取，库存默认返回有库存
    #                 cashierGiftSkuInfos_exp = []
    #                 if res_exp.get('cashierGiftSkuInfos') is not None:
    #                     cashierGiftSkuInfos_exp = res_exp['cashierGiftSkuInfos']
    #                 else:
    #                     if pro_info['baseInfo']['proType'] == '收银台赠品活动':
    #                         pro_rewards = pro_info['cashierRule']['rewards']
    #                         for reward in pro_rewards:
    #                             cashierGiftSkuInfos_exp.append(int(reward['rewardItemCode']))
    #                     else:
    #                         pro_rewards = pro_info['rule']['triggers']
    #                         for pro_reward in pro_rewards:
    #                             rewards = pro_reward['rewards']
    #                             for reward in rewards:
    #                                 reward_sku = int(reward.get('rewardItemCode', 0))
    #                                 if reward_sku not in cashierGiftSkuInfos_exp:
    #                                     cashierGiftSkuInfos_exp.append(reward_sku)
    #                 cashierGiftSkuInfos = []
    #                 for cashierGiftSkuInfo in res['cashierGiftSkuInfos']:
    #                     skuId = cashierGiftSkuInfo['skuId']
    #                     cashierGiftSkuInfos.append(skuId)
    #                     if cashierGiftSkuInfo['stockStatus'] != 1:
    #                         exc_value = '赠品{}的库存不正确，期望为：{}，实际为：{}'.format(proId_exp, skuId, 1,
    #                                                                                     cashierGiftSkuInfo[
    #                                                                                         'stockStatus'])
    #                         verification_res['stockStatus_{}'.format(skuId)] = [False, exc_value]
    #                         log_all.append({'error': '失败！！！{}'.format(exc_value)})
    #                 check_infos['赠品信息cashierGiftSkuInfos'] = [sorted(cashierGiftSkuInfos_exp),
    #                                                               sorted(cashierGiftSkuInfos)]
    #
    #                 # 校验giftTips。直接从促销详情中取
    #                 if res_exp.get('giftTips') is not None:
    #                     giftTips_exp = res_exp['giftTips']
    #                 else:
    #                     giftTips_exp = pro_info['showInfo']['showInfoPos']['cashierGiftTipsMap']
    #                 if self.offline_flag is False:  # 离线只会返回繁体中文促销语
    #                     check_infos['赠品提示语giftTips'] = [giftTips_exp[self.language], res['giftTips']]
    #                 else:
    #                     check_infos['赠品提示语giftTips'] = [giftTips_exp['zh_HK'], res['giftTips']]
    #
    #                 for key, value in check_infos.items():
    #                     if value[0] == value[1]:
    #                         verification_res[key] = [True]
    #                         log_all.append({'info': '成功！活动：{}，{}正确：{}'.format(proId_exp, key, value[0])})
    #                     else:
    #                         exc_value = '活动：{}，{}不正确，期望为：{}，实际为：{}'.format(proId_exp, key, value[0],
    #                                                                                   value[1])
    #                         verification_res[key] = [False, exc_value]
    #                         log_all.append({'error': '失败！！！{}'.format(exc_value)})
    #             verification_res_all[proId_exp] = verification_res
    #
    #     ids = []
    #     for cashierAlert in cashierAlerts:
    #         ids.append(cashierAlert['proId'])
    #     verification_res = {}
    #     if sorted(ids_exp) == sorted(ids):
    #         verification_res['cashierAlerts活动列表'] = [True]
    #         log_all.append({'info': 'cashierAlerts正确命中所有期望命中的收银台赠品活动：{}'.format(ids_exp)})
    #     else:
    #         exc_value = 'cashierAlerts期望命中收银台赠品活动校验不通过，期望命中活动：{},实际命中活动：{}'.format(
    #             sorted(ids_exp), sorted(ids))
    #         log_all.append({'error': '失败！！！{}'.format(exc_value)})
    #         verification_res['cashierAlerts活动列表'] = [False, exc_value]
    #     verification_res_all['cashierAlerts活动列表'] = verification_res
    #
    #     return verification_res_all, log_all

    def __check_total_price(self, res, res_separate, exps=[]):
        """
        根据规则，自动计算原价、优惠价和应付金额
        :param res_separate:
        :param exps:
        :return:
        """
        verification_res_all = {}
        log_all = [{'info': '\n'},
                   {'info': '================开始校验返回的实际应支付金额是否正确(自动计算应付金额)================'},
                   {
                       'info': '注意：自动计算依赖每个促销的proDicount正确，如果proDicount不正确，那么自动计算的结果也一定不正确'}]
        # 计算是否每个促销详情中都包含proDicount。包括0也必须传
        flag = 0
        for pro_info in exps:
            if pro_info.get('proDicount') is not None:
                flag += 1
        # 判断是走自动计算，还是直接跟写死的期望值进行对比
        if self.data.get('total_price_exp') is None and flag == len(exps):
            # 满足条件的话，就自动计算结果并进行校验
            pros = res_separate['pros']
            # 处理为促销id对应促销类型
            pros_type = {}
            for pro in pros:
                if pro['proId'] in pros_type.keys():
                    continue
                else:
                    pros_type[pro['proId']] = pro['proType']

            totalOrigPrice2 = 0
            # 计算原价
            ware_datas = self.ware_data
            for ware in ware_datas:
                totalOrigPrice2 += (ware['packNum'] * ware['packPrice'])
            # 计算优惠价
            totalDiscountAmount = 0
            totalDiscountAmount2 = 0
            orderProDiscountAmount = 0
            for pro_exp in exps:
                if pro_exp['proId_exp'] in pros_type.keys():
                    if pro_exp.get('proDicount'):
                        if pros_type[pro_exp['proId_exp']] == 'UNIT':
                            totalDiscountAmount2 += pro_exp['proDicount']
                        elif pros_type[pro_exp['proId_exp']] == 'BASKET':
                            orderProDiscountAmount += pro_exp['proDicount']
                        else:
                            totalDiscountAmount += pro_exp['proDicount']
                            totalDiscountAmount2 += pro_exp['proDicount']
            totalOrigPrice = totalOrigPrice2 - (totalDiscountAmount2 - totalDiscountAmount)
            orderTotalSettlePrice = totalOrigPrice - totalDiscountAmount - orderProDiscountAmount
            dict_exp = {'totalOrigPrice2': totalOrigPrice2, 'totalOrigPrice': totalOrigPrice,
                        'totalDiscountAmount': totalDiscountAmount,
                        'totalDiscountAmount2': totalDiscountAmount2, 'orderProDiscountAmount': orderProDiscountAmount,
                        'orderTotalSettlePrice': orderTotalSettlePrice}
            # 校验数据
            verification_res = {}
            for key, value in res.items():
                for key_exp, value_exp in dict_exp.items():
                    if key == key_exp:
                        if value != value_exp:
                            exc_value = '字段{}，期望与实际值不一致，自动计算出来的期望值为：{}，实际为：{}'.format(key,
                                                                                                               value_exp,
                                                                                                               value)
                            verification_res[key] = [False, exc_value]
                            log_all.append({'error': exc_value})
                        else:
                            verification_res[key] = [True]
                            log_all.append(
                                {'info': '字段{}，校验通过。自动计算出来的期望值为：{}。'.format(key_exp, value_exp)})
                        break
            verification_res_all['自动计算应付金额'] = verification_res
        # 不满足条件的话，按老逻辑，根据写死的期望值进行校验
        elif self.data.get('total_price_exp'):
            self.common.calc_result_check_price(res, self.data['total_price_exp'])
        else:
            exc_value = '当前proDicount有值的促销共：{}个。total_price_exp不传时，需要所有促销id对应的proDicount均有值才可以进行计算，请检查！！！'.format(
                flag)
            verification_res_all['自动计算应付金额'] = {'总proDicount个数': [False, exc_value]}
            log_all.append({'error': exc_value})

        return verification_res_all, log_all

    def calc_result_check_proSlogn(self, ticket, res_separate, exps=[]):
        """
        校验静态促销语

        :param res_separate:分解后的算价结果。格式：{'pros': pros_sort, 'shares': skus_share_info}
        :param exps:期望命中的促销列表，格式：exp = [{'proId_exp': 2021030500000881, 'proSlogan': 'XX', 'showSlogan': 'XX'}]
        """
        verification_res_all = {}
        log_all = [{'info': '\n'}, {'info': '================开始校验返回的促销语相关信息================'}]
        pros = res_separate['pros']
        for exp in exps:
            verification_res = {}
            proId_exp = exp['proId_exp']
            for pro in pros:
                if proId_exp == pro['proId']:
                    displayInfo = pro['displayInfo']
                    # 因为线上线下均返回静态促销语，所以可以直接校验促销语
                    address_proengine = self.env_hosts['partnerPro']
                    proInfo = ProInfo(address_proengine)
                    pro_info = proInfo.pro_view(ticket, pro['proId'])
                    showModuleInfo_exp = pro_info['showModuleInfo']
                    print('showModuleInfo_exp:', showModuleInfo_exp)

                    verification_res = {}
                    # 需要校验的字段对应关系
                    filed = {'proTag': 'showTagMap', 'proSlogan': 'showSloganMap', 'proLimitDesc': 'showLimitDescMap',
                             'exemptionTipDesc': 'exemptionTipDescMap'}
                    for key, key_exp in filed.items():
                        if displayInfo.get(key) is not None:
                            if self.offline_flag is False:  # 离线只会返回繁体中文促销语
                                verification_res[key] = pytest.assume(
                                    displayInfo[key] == showModuleInfo_exp[key_exp][self.language],
                                    '促销{}接口返回的{}校验不通过，期望：{}，实际返回：{}'.format(pro['proId'], key,
                                                                                              showModuleInfo_exp[
                                                                                                  key_exp],
                                                                                              displayInfo[key]))
                            else:
                                verification_res[key] = pytest.assume(
                                    displayInfo[key] == showModuleInfo_exp[key_exp]['zh_HK'],
                                    '促销{}接口返回的{}校验不通过，期望：{}，实际返回：{}'.format(pro['proId'], key,
                                                                                              showModuleInfo_exp[
                                                                                                  key_exp],
                                                                                              displayInfo[key]))

            verification_res_values = []
            for value in verification_res.values():
                verification_res_values.append(value[0])
            if False in verification_res_values:
                err = []
                for key, value in verification_res.items():
                    if False in value:
                        err.append(key)
                log_all.append({'error': '失败！！！促销：{}，存在校验失败字段，具体字段列表：{}'.format(proId_exp, err)})
            else:
                log_all.append(
                    {'info': '成功！促销：{}，所有字段值校验均正确：{}'.format(proId_exp, list(verification_res.keys()))})
            verification_res_all[proId_exp] = verification_res


pro_type = {1: 'UNIT', 2: 'AMOUNT', 3: 'QUANTITY', 4: 'PWP', 5: 'MATCH', 6: 'REDEEM', 7: 'BRAND', 8: 'CATE',
            9: 'BASKET', 10: 'SPECIAL_IDENTITY', 11: 'PAYMENT', 12: 'PAYMENT_FREEBIE', 13: '收银台赠品活动'}


def check_res_data(data, expect_data):
    """
    线下促销校验器
    """
    res = json.loads(data).get('response', None)
    if res:
        res_json = json.dumps(res)
        res_str = res_json.replace('\\n', '').replace('\\t', '').replace('false', 'False').replace('true', 'True')
        res_j = json.loads(res_str)
        res_data = eval(res_j)
        res_code = res_data['code']
        if res_code == 'PRO000':
            res_data = res_data['data']
            try:
                res_data_dic = json.loads(json.dumps(res_data))
            except Exception as e:
                res_data_dic = demjson.decode(res_data)  # 转成标准的json格式
        else:
            res_data_json = json.dumps(res_data).encode('utf-8').decode('unicode_escape')  # 将\\uxxxx转为Unicode字符串
            raise Exception('接口返回报错，报错信息为：{}'.format(data.json()))
        expect_data.update({'ware_data': req_wares})
        oc = OfflineCalc(**expect_data)
        separate = oc.result_separate(res_data_dic)
        result = oc.result_check(res_data_dic, separate, expect_data['proInfo_exp'])
        print('执行完成############')
        assert True
    else:
        raise Exception('接口返回报错，报错信息为：{}'.format(json.dumps(data.json())))


def setup_hook_prepare_json(request):
    """
    预处理 request 参数
    """
    data = {
        'className': 'com.rta.promotion.client.api.PromoOfflineService',
        'methodName': 'calcPromotion',
        'params': []
    }
    print('###########')
    if isinstance(request["json"], dict):
        ware_data = request['json']['ware_data']
        global req_wares
        req_wares = ware_data
        main_data = request['json']['mainData']
        other_data = request['json'].get('otherData', [])
        barCodeList = request['json'].get('barCodeList', None)
        params = __build_params(ware_data, main_data, barCodeList=barCodeList, other_data=other_data)
        data.update({'params': [params]})
        request['json'] = data
        print('###########111111111111')


def __build_params(ware_data, main_data, **kwargs):
    """构建接口入参"""
    addTime = int(time.time() * 1000)
    uniqueId = ''.join(random.sample(string.ascii_letters + string.digits, 10))
    skus = []
    for sku_info in ware_data:
        sku = {
            "addTime": addTime,
            "buyQty": 0,
            "checked": True,
            "jointFlag": 99,
            "matchSimplePro": True,
            "origPrice": 0,
            "packNum": 0,
            "packPrice": 0,
            "pluType": 5,
            "skuId": 0,
            "skuName": "商品名称",
            "skuType": "MAIN_SKU",
            "storeId": main_data['storeId'],
            "unitPackCount": 1,
            "venderId": main_data['venderId'],
            "wareType": "NORMAL",
            "wareWeight": 1.0,
            "uniqueId": uniqueId + '_' + str(sku_info['skuId']) + '_' + str(addTime),
            "priceChanged": False,
            "catExtendInfo": sku_info.get('catExtendInfo', {}),
            "extendInfoMap": sku_info.get('extendInfoMap', {})
        }
        # skuId/packNum/packPrice三个属于必传字段，如果没传，直接报错
        assert 'skuId' in sku_info.keys() and 'packNum' in sku_info.keys() and 'packPrice' in sku_info.keys(), '商品skuId、packNum和packPrice为必传属性！请检查数据：{}'.format(
            sku_info)
        for info_k, info_v in sku_info.items():
            # 商家id应该是统一确定的，不可以自定义
            if info_k not in ['venderId']:
                sku[info_k] = info_v
        skus.append(sku)
        addTime += 1
    data = {
        "anfieldMember": False,
        "barCodeList": kwargs.get('barCodeList', []),
        "calcMemberPrice": False,
        "invokeSysName": "python",
        "platForm": main_data.get('channel', 'POS'),  # POS, SELF_CHECKOUT, SCAN_AND_GO
        "skus": skus,
        "storeId": main_data['storeId'],
        "storeName": "python門店名",
        "terminal": "PC",
        "userId": 111222,
        "userTypes": main_data.get('userTypes', []),  # None, USER_RTA, USER_YUU
        "venderId": main_data['venderId'],
        "staffPromoCalcPara": main_data.get('staffPromoCalcPara', None),
        "venderName": "自动化商家",
        "showCashierAlert": False
    }

    # for others_k, others_v in self.others_data.items():
    #     # skus不可以自定义
    #     if others_k not in ['skus', 'venderId']:
    #         data[others_k] = others_v
    return data
